예제 #1
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)
예제 #2
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()
예제 #3
0
class OutputWidget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, None)
        self.layout = QGridLayout()

        self.label = QLabel("Files selected:")
        self.layout.addWidget(self.label, 0, 0, 1, 4)

        self.file_list = QListWidget()
        self.select_all = QListWidgetItem("(De)select all")
        self.select_all.setFlags(self.select_all.flags()
                                 | Qt.ItemIsUserCheckable)
        self.select_all.setCheckState(Qt.Unchecked)
        self.file_list.addItem(self.select_all)

        self.layout.addWidget(self.file_list, 1, 0, 1, 4)
        self.layout.addWidget(QLabel("First line:"), 2, 0)
        self.first_line = QLineEdit("", self)
        self.first_line.setValidator(QIntValidator(1, 100000))
        self.layout.addWidget(self.first_line, 2, 1)
        self.layout.addWidget(QLabel("Last line:"), 2, 2)
        self.last_line = QLineEdit("", self)
        self.last_line.setValidator(QIntValidator(1, 100000))
        self.layout.addWidget(self.last_line, 2, 3)
        self.convert_button = QPushButton("EXPORT")
        self.convert_button.clicked.connect(parent.on_convert)
        self.convert_button.setStyleSheet("background-color: green")
        self.layout.addWidget(self.convert_button, 3, 0, 1, 4)
        self.setLayout(self.layout)
        self.list_items = {}

        self.file_list.itemChanged.connect(self.on_item_changed)

    def add_to_list(self, file):
        if (self.list_items.get(file)):
            return False
        list_item = QListWidgetItem(file)
        list_item.setFlags(list_item.flags() | Qt.ItemIsUserCheckable)
        list_item.setCheckState(Qt.Checked)
        self.file_list.addItem(list_item)
        self.list_items[file] = list_item
        return True

    def remove_from_list(self, file):
        list_item = self.list_items.pop(file, None)
        if (not list_item):
            return False
        self.file_list.takeItem(self.file_list.row(list_item))
        if (len(self.list_items) == 0):
            self.select_all.setCheckState(Qt.Unchecked)
        return True

    def output_info(self):
        res = {
            "files":
            self.files_selected(),
            "first_line":
            (0 if not self.last_line.text() else int(self.first_line.text())),
            "last_line":
            (0 if not self.last_line.text() else int(self.last_line.text()))
        }
        return res

    def on_item_changed(self, item):
        if (item is self.select_all):
            for list_item in self.list_items.values():
                list_item.setCheckState(self.select_all.checkState())

    def files_selected(self):
        res = []
        for list_item in self.list_items.values():
            if (list_item.checkState() == Qt.Checked):
                res.append(list_item.text())
        return res
예제 #4
0
class CreateSequenceWindow(QDialog):
    """
    Window for creating a new sequence
    """
    def __init__(self,
                 motors={},
                 listOfSequenceHandler=None,
                 sequence=None,
                 modifySequence=False):
        """
        Initializtion of the window for creating a new sequence
        :param motors: The dictionary of all the motors
        :param listOfSequenceHandler: The handler of the list of sequence
        """
        QDialog.__init__(self)
        # Set the window icon
        appIcon = QIcon(icon)
        self.setWindowIcon(appIcon)

        ## Flag if the sequence is a modified one or a new one
        self.__modifySequence = modifySequence
        ## The handler of the list of sequence
        self.__listOfSequenceHandler = listOfSequenceHandler
        ## The dictionary of all the motors
        self.__motors = motors
        ## The new sequence
        self.__sequence = sequence
        ## A dictionary of the positions of the new sequence
        self.__wantedPositions = {}
        ## The layout of the create sequence window
        self.__layout = QVBoxLayout(self)
        ## The widget for the name of the sequenc
        self.nameEntry = QLineEdit()
        self.nameEntry.setText(self.__sequence.getName())
        ## The label for the widget in which the name of the sequence is written
        self.__nameLabel = QLabel("Sequence Name")
        ## The list of the different moves that forms the sequence
        self.__listOfMoveLabels = QListWidget()
        moveNumber = 1
        for move in self.__sequence.getMoves():
            # Set text for the move label
            labelText = "move " + str(moveNumber) + ": "
            moveNumber += 1
            for motor in self.__motors:
                labelText += self.__motors[motor].getName() + " " + \
                             str(move.getMotorPosition(self.__motors[motor].getName())) + ", "
            label = moveLabel(move, labelText, self.__motors)

            # insert label to the head of the list
            self.__listOfMoveLabels.insertItem(0, label)

        # Put the sliders of the create sequence window in a list
        ## List of sliders in the create sequence window
        self.listOfSliders = []
        dictOfSlider = dict()

        for motor in self.__motors:
            dictOfSlider[motor] = QSlider(Qt.Horizontal)
            dictOfSlider[motor].setMaximum(4095)
            dictOfSlider[motor].setValue(
                self.__motors[motor].getCurrentPosition())
            dictOfSlider[motor].sliderMoved.connect(
                self.__motors[motor].setGoalPosition)
            self.listOfSliders.append(dictOfSlider[motor])

        ## Message to make the user put a name to the sequence
        self.__noNameMessage = QMessageBox()
        self.__noNameMessage.setIcon(QMessageBox.Warning)
        self.__noNameMessage.setWindowIcon(appIcon)
        self.__noNameMessage.setText(
            "Please name your sequence before saving it")
        self.__noNameMessage.setStandardButtons(QMessageBox.Ok)
        # Renable the create sequence window and closes the message
        self.__noNameMessage.accepted.connect(self.enableWindow)

        ## Warning message to make sure the user doen't want to save the sequence
        self.__warningMessage = QMessageBox()
        self.__warningMessage.setIcon(QMessageBox.Warning)
        self.__warningMessage.setWindowIcon(appIcon)
        self.__warningMessage.setText(
            "Are you sure you want to close this window? Your sequence will not be saved"
        )
        self.__warningMessage.setStandardButtons(QMessageBox.Ok
                                                 | QMessageBox.Cancel)
        # Close the create sequence window and the message
        self.__warningMessage.accepted.connect(self.reject)
        # Renable the create sequence window and closes the message
        self.__warningMessage.rejected.connect(self.enableWindow)

        # Set the text for the labels
        ## Labels for the motors in the UI
        self.__motorLabels = []
        for motorNumber in range(0, len(motors)):
            self.__motorLabels.append(
                QLabel("Motor " + str(motorNumber + 1) + " position"))

        ## Button to add a move to the sequence and procede to the next move
        self.nextMoveButton = QPushButton("Save Move")

        ## Buttons to accept or cancel the creation of a sequence
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        # If ok pressed add the sequence to the list
        self.buttonBox.accepted.connect(
            lambda: self.addSequenceToList(self.__modifySequence))
        # If cancel pressed close the create sequence window
        self.buttonBox.rejected.connect(self.__warningMessage.exec)

        # Renable the main window when the create sequence closes
        self.rejected.connect(self.__listOfSequenceHandler.enableUi)
        self.accepted.connect(self.__listOfSequenceHandler.enableUi)

        self.nextMoveButton.clicked.connect(self.addMovetoSequence)

        self.__listOfMoveLabels.itemDoubleClicked.connect(
            self.moveDoubleClicked)

        # Build the vertical layout with the different widgets
        self.__layout.addWidget(self.__nameLabel)
        self.__layout.addWidget(self.nameEntry)
        self.__layout.addWidget(self.__listOfMoveLabels)
        for motorNumber in range(len(self.__motors)):
            self.__layout.addWidget(self.__motorLabels[motorNumber])
            self.__layout.addWidget(self.listOfSliders[motorNumber])
        self.__layout.addWidget(self.nextMoveButton)
        self.__layout.addWidget(self.buttonBox)

        # Connect the qwidgetlist to the custom right click menu
        self.__listOfMoveLabels.setContextMenuPolicy(Qt.CustomContextMenu)
        self.__listOfMoveLabels.customContextMenuRequested.connect(
            self.rightClickMenu)

    def setName(self, name):
        """
        Sets the name of the sequence with the user input
        :param name: The name of the sequence
        :return: No return
        """
        self.__sequence.setName(name)

    def getSequence(self):
        """
        Accessor of the sequence (for tests)
        :return: the sequence
        """
        return self.__sequence

    def getListofMoveLabels(self):
        """
        Accessor of the list of move labels (for tests)
        :return: the list of move labels
        """
        return self.__listOfMoveLabels

    def addSequenceToList(self, modifySequence=False):
        """
        Add the sequence to the list of sequence
        :param modifySequence: bool, if true there's a selected sequence that needs to be modified if false
        it's a new sequence
        :return: No return
        """
        # TODO: look to move this method to the list of sequence handler
        # TODO: don't let the user enter a sequence that has the same name as an old one
        self.setName(self.nameEntry.text())
        if self.__sequence.getName() != "":
            # Load previously saved sequences
            try:
                with open('SaveSequence.json') as save:
                    savedListOfSequences = json.load(save)
            except FileNotFoundError:
                savedListOfSequences = []

            if modifySequence:
                # Get the item that needs to be modified
                # selectedSequence = self.__listOfSequenceHandler.getSelectedItems()
                # Find the selected sequence in the list of saved ones
                for sequence in savedListOfSequences:
                    if self.__sequence.getName() in sequence:
                        indexOfTheSequence = savedListOfSequences.index(
                            sequence)
                        # remove the unmodified sequence to insert the modified sequence
                        savedListOfSequences.remove(sequence)
                        self.__listOfSequenceHandler.addItem(self.__sequence)
                        # Make the sequence json seriable
                        newSequence = dict()
                        newSequence[self.__sequence.getName()] = []
                        for moveNumber in range(len(
                                self.__sequence.getMoves())):
                            newSequence[self.__sequence.getName()].append(
                                self.__sequence.getMoves()
                                [moveNumber].getMovePositions())

                        # Append new sequence to the old ones
                        savedListOfSequences.insert(indexOfTheSequence,
                                                    newSequence)

                        # Write the sequences to the file
                        with open('SaveSequence.json', 'w') as outfile:
                            json.dump(savedListOfSequences, outfile)

                        self.accept()
            else:
                self.__listOfSequenceHandler.addItem(self.__sequence)
                # Make the sequence json seriable
                newSequence = dict()
                newSequence[self.__sequence.getName()] = []
                for moveNumber in range(len(self.__sequence.getMoves())):
                    newSequence[self.__sequence.getName()].append(
                        self.__sequence.getMoves()
                        [moveNumber].getMovePositions())

                # Append new sequence to the old ones
                savedListOfSequences.append(newSequence)

                # Write the sequences to the file
                with open('SaveSequence.json', 'w') as outfile:
                    json.dump(savedListOfSequences, outfile)

                self.accept()
        else:
            self.setEnabled(False)
            self.__noNameMessage.exec_()

    def addMovetoSequence(self):
        """
        Add the last move to the sequence
        :return: No return
        """
        move = None
        labelToModify = None
        # Check if there's a move in modifying state
        for row in range(self.__listOfMoveLabels.count()):
            if not self.__listOfMoveLabels.item(row).getMove().isNew:
                move = self.__listOfMoveLabels.item(row).getMove()
                labelToModify = self.__listOfMoveLabels.item(row)
                break
        # verify if the move is a new one
        if move is None:
            # Create the new move and set his positions
            move = Move(self.__motors)
            i = 0
            for motorName in self.__motors:
                move.setMotorPosition(motorName, self.listOfSliders[i].value())
                i += 1
            self.__sequence.addMove(move)

            # Set text for the move label
            labelText = "move " + str(
                self.__sequence.getNumberofMoves()) + ": "
            i = 0
            for motor in self.__motors:
                labelText += self.__motors[motor].getName() + " " +\
                             str(self.listOfSliders[i].value()) + ", "
                i += 1
            label = moveLabel(move, labelText, self.__motors)

            # insert label to the head of the list
            self.__listOfMoveLabels.insertItem(0, label)
        else:
            # modify the move
            i = 0
            for motorName in self.__motors:
                move.setMotorPosition(motorName, self.listOfSliders[i].value())
                i += 1

            # modify the label of the move
            textToEdit = labelToModify.text()
            listOfTextToEdit = textToEdit.split(' ')
            labelText = listOfTextToEdit[0] + " " + listOfTextToEdit[1] + " "
            i = 0
            for motor in self.__motors:
                labelText += self.__motors[motor].getName() + " " + \
                             str(self.listOfSliders[i].value()) + ", "
                i += 1
            labelToModify.setText(labelText)
            labelToModify.setSelected(False)
            labelToModify.setBackground(Qt.white)

            # reset the state of the move
            move.isNew = True

    # Access the move positions when double clicked on
    def moveDoubleClicked(self, moveItem):
        """
        Called when a move in the sequence is double clicked
        :param moveItem: the move that was double clicked
        :return: No return
        """
        moveItem.goToMoveOfTheLabel()
        self.updateSlidersPositions()

    def updateSlidersPositions(self):
        counterMotors = 0
        for motor in self.__motors:
            self.listOfSliders[counterMotors].setValue(
                self.__motors[motor].getGoalPosition())
            counterMotors += 1

    def enableWindow(self):
        """
        Enable the create sequence window
        :return:
        """
        self.setEnabled(True)

    def rightClickMenu(self, event):
        """
        The right click menu of the move list
        :param event: The event (here right click) that makes the menu come up
        :return: No return
        """
        menu = QMenu()
        # Add a button in the menu that when clicked, it puts a move in modifying state
        menu.addAction(
            "Modify Move", lambda: self.modifyMove(self.__listOfMoveLabels.
                                                   selectedItems()[0]))
        # Add a button in the menu that when clicked, it deletes a move in the list
        menu.addAction(
            "Delete Move", lambda: self.deleteMove(self.__listOfMoveLabels.
                                                   selectedItems()[0]))
        menu.exec_(self.__listOfMoveLabels.mapToGlobal(event))

    def deleteMove(self, label):
        """
        Delete a move and its label of the sequence
        :param label: label of the move
        :return: No return
        """
        # remove the label from the list
        self.__listOfMoveLabels.takeItem(self.__listOfMoveLabels.row(label))
        # remove the move from the sequence
        self.__sequence.deleteMove(label.getMove())

        # rename the labels in the list of moves
        for index in range(self.__sequence.getNumberofMoves() - 1, -1, -1):
            labelToModify = self.__listOfMoveLabels.item(index)
            textToEdit = labelToModify.text()
            listOfTextToEdit = textToEdit.split(' ')
            listOfTextToEdit[1] = str(self.__sequence.getNumberofMoves() -
                                      index) + ':'
            textToEdit = ' '.join(listOfTextToEdit)
            self.__listOfMoveLabels.item(index).setText(textToEdit)

    def modifyMove(self, label):
        """
        Put a move to a modified state
        :param label: label of the move
        :return: No return
        """
        # Check if there's a move in modifying state
        for row in range(self.__listOfMoveLabels.count()):
            if not self.__listOfMoveLabels.item(row).getMove().isNew:
                self.__listOfMoveLabels.item(row).getMove().isNew = True
                self.__listOfMoveLabels.item(row).setBackground(
                    QBrush(Qt.white))

        moveToModify = label.getMove()
        moveToModify.isNew = False
        label.setBackground(QBrush(Qt.darkCyan))
        label.goToMoveOfTheLabel()
        self.updateSlidersPositions()
예제 #5
0
class ExerciseWindow(QWidget):
    closed = Signal()

    def __init__(self, nursery, exercise):
        super().__init__()
        self.log = logging.getLogger("Test qt lean")

        self.server = ServerInterface(nursery)

        self.exercise = exercise
        self.statements = self.exercise.course.statements

        self._initUI()

        # Link signals
        self.server.proof_state_change.connect(self.proof_state_update)

        # Start waiter task
        self.server.nursery.start_soon(self.server_task)

        # Update initial proof state
        #self.proof_state_update(self.server.proof_state)

    async def server_task(self):
        await self.server.start()
        await self.server.exercise_set(self.exercise)
        async with qtrio.enter_emissions_channel(
                signals=[self.closed, self.send.clicked, self.undo.clicked
                         ]) as emissions:
            async for emission in emissions.channel:
                if emission.is_from(self.closed):
                    break
                elif emission.is_from(self.send.clicked):
                    await self.go_send()
                elif emission.is_from(self.undo.clicked):
                    await self.go_undo()

        self.server.stop()

    async def go_send(self):
        self.log.info("Send file to lean")
        self.freeze(True)

        txt = self.edit.toPlainText()
        try:
            await self.server.code_set("add", txt)
        except exceptions.FailedRequestError as ex:
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Critical)
            msg.setWindowTitle("Failed lean request")
            msg.setText("I am broken :'(")

            detailed = ""
            for err in ex.errors:
                detailed += f"* at {err.pos_line} : {err.text}\n"

            msg.setDetailedText(detailed)
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()

        self.freeze(False)

    async def go_undo(self):
        self.log.info("Undo")
        self.freeze(True)
        await self.server.history_undo()
        self.edit.setPlainText(self.server.lean_file.inner_contents)
        self.freeze(False)

    def closeEvent(self, ev):
        super().closeEvent(ev)
        self.closed.emit()

    def _initUI(self):
        # Create widgets
        self.objects = PropobjList()
        self.properties = PropobjList()

        self.goal = Goal("TODO")

        self.edit = QPlainTextEdit()
        self.send = QPushButton("Send to lean")
        self.undo = QPushButton("Undo")

        self.deflist = QListWidget()

        # --> Build deflist
        for st in self.statements:
            self.deflist.addItem(st.pretty_name)

        # --> Link signal
        self.deflist.itemClicked.connect(self.add_statement_name)

        # Create layouts
        goal_layout = QHBoxLayout()
        main_layout = QVBoxLayout()
        workspace_layout = QHBoxLayout()
        propobj_layout = QVBoxLayout()
        tools_layout = QVBoxLayout()
        btns_layout = QHBoxLayout()

        # Create QGroupBox to have titles
        propobj_gb = QGroupBox('Properties and objects')
        self.tools_gb = QGroupBox('Lean code')

        # Put widgets in layouts and group boxes
        goal_layout.addStretch()
        goal_layout.addWidget(self.goal)
        goal_layout.addStretch()

        # Add space below goal
        goal_layout.setContentsMargins(0, 10, 0, 30)  #LTRB

        # Build propobj layout
        propobj_layout.addWidget(self.objects)
        propobj_layout.addWidget(self.properties)
        propobj_gb.setLayout(propobj_layout)

        # Build tools layout
        btns_layout.addWidget(self.send)
        btns_layout.addWidget(self.undo)

        tools_layout.addWidget(self.deflist)
        tools_layout.addWidget(self.edit)
        tools_layout.addLayout(btns_layout)

        self.tools_gb.setLayout(tools_layout)

        # Build workspace layout
        workspace_layout.addWidget(propobj_gb)
        workspace_layout.addWidget(self.tools_gb)

        # Don't forget me
        main_layout.addLayout(goal_layout)
        main_layout.addLayout(workspace_layout)
        self.setWindowTitle("d∃∀duction")
        self.setLayout(main_layout)
        self.show()

    def freeze(self, state: bool):
        self.tools_gb.setEnabled(not state)

    @Slot(QListWidgetItem)
    def add_statement_name(self, item):
        st = self.statements[self.deflist.row(item)]
        self.edit.insertPlainText(st.lean_name)

    @Slot(ProofState)
    def proof_state_update(self, po: ProofState):
        # Update goal
        # log.debug("Updating goal")
        goal = po.goals[0]
        target = goal.target.math_type.format_as_utf8()

        self.goal.setText(target)

        # Update properties and objects
        self.properties.clear()
        self.objects.clear()
        for type_, instances in goal.math_types:
            utf8 = type_.format_as_utf8(is_math_type=True)

            for obj in instances:
                txt = f"{obj.format_as_utf8()} : {utf8}"
                if obj.is_prop(): self.properties.addItem(txt)
                else: self.objects.addItem(txt)