def add_fields_to_component(component: Component, fields_widget: QListWidget):
    """
    Adds fields from a list widget to a component.
    :param component: Component to add the field to.
    :param fields_widget: The field list widget to extract field information such the name and value of each field.
    """
    for i in range(fields_widget.count()):
        widget = fields_widget.itemWidget(fields_widget.item(i))
        try:
            component.set_field(name=widget.name,
                                value=widget.value,
                                dtype=widget.dtype)
        except ValueError as error:
            show_warning_dialog(
                f"Warning: field {widget.name} not added",
                title="Field invalid",
                additional_info=str(error),
                parent=fields_widget.parent().parent(),
            )
Exemple #2
0
class Ui_MainWindow(object):

    image_stack=[None]
    current_effect=""
    def resize(self):
        self.timer.stop()
        temp=QDialog()
        temp.ui=Ui_Dialog_Resize(self.image_stack[-1])
        temp.ui.setupUi(temp)
        temp.show()
        temp.exec_()
        self.image_stack.append(temp.ui.image)
        self.timer.start(1)
        pass

    def cropping(self):
        if type(self.image_stack[-1])==type(None):
            print("lol")
            return
        self.timer.stop()
        temp=QDialog()
        temp.ui=Ui_Dialog(self.image_stack[-1])
        temp.ui.setupUi(temp)
        temp.show()
        temp.exec_()
        self.image_stack.append(temp.ui.image)
        self.timer.start(1)
        pass

    def effectFuctions(self,effect,image,amount):
        if effect=="Brightness":
            return brightness(image, amount=amount)
        elif effect=="Saturation":
            return saturation(image, amount)
        elif effect=="Sharpen":
            return sharpness(image, amount)
        elif effect=="Sepia Effect":
            return sepia(image, amount)
        elif effect=="Warm":
            return warm(image, amount)
        elif effect == "Cold":
            return cold(image, amount)
        elif effect == "Equalize":
            return equalise(image, amount)
        elif effect== "Cartoon":
            return cartoon(image, amount)
        elif effect== "Blurring":
            return blurring(image, amount) 
        elif effect== "Pencil Sketch":
            return pencil_sketch(image, amount)
        elif effect== "Noise Reduction":
            return noise_reduction(image, amount)
        elif effect== "Negetive" :
            return negative(image, amount)
        elif effect== "Vignette":  
            return vignette(image, amount)
        elif effect== "Emboss":
            return emboss(image, amount)
        elif effect== "Redden": # lal panni
            return redden(image, amount)
        elif effect== "Greenify": # hari panni 
            return greenify(image, amount)
        elif effect== "Bloom Blue": # nili panni 
            return nili_panni(image, amount)
        elif effect== "HDR":  
            return hdr(image, amount)
        elif effect== "Yellow":  
            return yellow_panni(image, amount)


    def showFrame(self,frame):
        if type(frame)==type(None):
            self.label.setText(QCoreApplication.translate("MainWindow", u"<html><head/><body style=\"background-color:powderblue;\"><p align=\"center\">Your Image Here</p></body></html>", None))
            return
        if self.listWidget.selectedItems()!=[]:
            effect=self.listWidget.selectedItems()[0].text()
            if effect!=self.current_effect:
                print("LOL")
                self.current_effect=effect
                clearTemp()
            temp=self.effectFuctions(effect,frame.copy(),self.horizontalSlider.value())
            frame= temp if type(temp)!=type(None) else frame
        
        frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
        image=qimage2ndarray.array2qimage(frame)
        self.label.setPixmap(QPixmap.fromImage(image))
        pass

    def addImage(self):
        #
        self.image_stack=[None]
        filePath,_=QFileDialog.getOpenFileName(QMainWindow(), 'Open file')
        self.image_stack.append(cv2.imread(filePath))
        pass

    def saveImage(self):
        #print("lol")
        filePath,_=QFileDialog.getSaveFileName(QMainWindow(),"Choose the save location")
        self.label.pixmap().save(filePath,"jpg",100)
        
        #self.cv2.imwrite(filePath,self.image_stack[-1])
        #pass
    
    def commit(self):
        frame=self.image_stack[-1]
        if self.listWidget.selectedItems()==[]:
            return
        effect=self.listWidget.selectedItems()[0].text()
        temp=self.effectFuctions(effect,frame,self.horizontalSlider.value())
        #frame= temp if type(temp)!=type(None) else None
        if type(frame)!=type(None):
            self.image_stack.append(temp)
        self.horizontalSlider.setValue(0)
        self.listWidget.setCurrentItem(None)

    def cancle(self):
       self.horizontalSlider.setValue(0)
       self.listWidget.setCurrentItem(None)

    def undo(self):
        if type(self.image_stack)!=type(None):
            self.image_stack.pop()

    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(1131, 555)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.label = QLabel(self.centralwidget)
        self.label.setObjectName(u"label")
        self.label.setGeometry(QRect(10, 60, 781, 431))
        self.label.setStyleSheet(u"background-color: rgb(85, 255, 255)")
        self.label.setScaledContents(True)
        
        self.listWidget = QListWidget(self.centralwidget)
        no_of_widgets=19
        for i in range(no_of_widgets):
            QListWidgetItem(self.listWidget)
        self.listWidget.setObjectName(u"listWidget")
        self.listWidget.setGeometry(QRect(850, 160, 256, 201))

        self.horizontalSlider = QSlider(self.centralwidget)
        self.horizontalSlider.setObjectName(u"horizontalSlider")
        self.horizontalSlider.setGeometry(QRect(870, 70, 211, 22))
        self.horizontalSlider.setOrientation(Qt.Horizontal)
        #print(self.horizontalSlider.value())
        self.label_2 = QLabel(self.centralwidget)
        self.label_2.setObjectName(u"label_2")
        self.label_2.setGeometry(QRect(930, 10, 101, 51))
        self.label_2.setMinimumSize(QSize(0, 31))
        self.label_2.setScaledContents(True)
        self.label_2.setWordWrap(True)
        self.label_2.setMargin(10)
        
        # ✅ commit button
        self.pushButton = QPushButton(self.centralwidget)
        self.pushButton.setObjectName(u"pushButton")
        self.pushButton.setGeometry(QRect(892, 110, 61, 28))
        self.pushButton.clicked.connect(lambda : self.commit())

        # ❌ cancle button
        self.pushButton_2 = QPushButton(self.centralwidget)
        self.pushButton_2.setObjectName(u"pushButton_2")
        self.pushButton_2.setGeometry(QRect(990, 110, 61, 28))
        self.pushButton_2.clicked.connect(lambda : self.cancle())

        # ↩️ Undo button
        self.pushButton_3 = QPushButton(self.centralwidget)
        self.pushButton_3.setObjectName(u"pushButton_3")
        self.pushButton_3.setGeometry(QRect(370, 20, 61, 28))
        self.pushButton_3.clicked.connect(lambda : self.undo())

        #crop
        self.pushButton_4 = QPushButton(self.centralwidget)
        self.pushButton_4.setObjectName(u"pushButton_4")
        self.pushButton_4.setGeometry(QRect(910, 380, 61, 28))
        self.pushButton_4.clicked.connect(self.cropping)
        
        # Resize
        self.pushButton_5 = QPushButton(self.centralwidget)
        self.pushButton_5.setObjectName(u"pushButton_5")
        self.pushButton_5.setGeometry(QRect(980, 380, 61, 28))
        self.pushButton_5.clicked.connect(self.resize)
        
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")

        self.menubar.setGeometry(QRect(0, 0, 1131, 26))
        self.menuNew_File = QMenu(self.menubar)
        self.menuNew_File.setObjectName(u"menuNew_File")

        #New File
        self.actionNew_File = QAction("NewFile")
        self.actionNew_File.triggered.connect(self.addImage)
        self.menuNew_File.addAction(self.actionNew_File)

        #Save File
        self.actionSave_File = QAction("SaveFile")
        self.actionSave_File.triggered.connect(self.saveImage)
        self.menuNew_File.addAction(self.actionSave_File)

        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")

        self.timer=QTimer()
        self.timer.timeout.connect(lambda : self.showFrame(self.image_stack[-1]) ) 
        self.timer.start(1)

        MainWindow.setStatusBar(self.statusbar)

        self.menubar.addAction(self.menuNew_File.menuAction())
        #self.menubar.addAction(self.menuSave.menuAction())

        self.retranslateUi(MainWindow)

        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
        self.label.setText(QCoreApplication.translate("MainWindow", u"<html><head/><body style=\"background-color:powderblue;\"><p align=\"center\">Your Image Here</p></body></html>", None))

        __sortingEnabled = self.listWidget.isSortingEnabled()
        self.listWidget.setSortingEnabled(False)
        ___qlistwidgetitem = self.listWidget.item(0)
        ___qlistwidgetitem.setText(QCoreApplication.translate("MainWindow", u"Brightness", None));
        ___qlistwidgetitem1 = self.listWidget.item(1)
        ___qlistwidgetitem1.setText(QCoreApplication.translate("MainWindow", u"Saturation", None));
        ___qlistwidgetitem2 = self.listWidget.item(2)
        ___qlistwidgetitem2.setText(QCoreApplication.translate("MainWindow", u"Sharpen", None));
        ___qlistwidgetitem3 = self.listWidget.item(3)
        ___qlistwidgetitem3.setText(QCoreApplication.translate("MainWindow", u"Sepia Effect", None));
        ___qlistwidgetitem4 = self.listWidget.item(4)
        ___qlistwidgetitem4.setText(QCoreApplication.translate("MainWindow", u"Warm", None));
        ___qlistwidgetitem5 = self.listWidget.item(5)
        ___qlistwidgetitem5.setText(QCoreApplication.translate("MainWindow", u"Cold", None));
        ___qlistwidgetitem6 = self.listWidget.item(6)
        ___qlistwidgetitem6.setText(QCoreApplication.translate("MainWindow", u"Equalize", None));
        ___qlistwidgetitem7 = self.listWidget.item(7)
        ___qlistwidgetitem7.setText(QCoreApplication.translate("MainWindow", u"Cartoon", None));
        ___qlistwidgetitem8 = self.listWidget.item(8)
        ___qlistwidgetitem8.setText(QCoreApplication.translate("MainWindow", u"Blurring", None)); 
        ___qlistwidgetitem9 = self.listWidget.item(9)
        ___qlistwidgetitem9.setText(QCoreApplication.translate("MainWindow", u"Pencil Sketch", None)); 
        ___qlistwidgetitem10 = self.listWidget.item(10)
        ___qlistwidgetitem10.setText(QCoreApplication.translate("MainWindow", u"Noise Reduction", None));
        ___qlistwidgetitem11 = self.listWidget.item(11)
        ___qlistwidgetitem11.setText(QCoreApplication.translate("MainWindow", u"Negetive", None));
        ___qlistwidgetitem12 = self.listWidget.item(12)
        ___qlistwidgetitem12.setText(QCoreApplication.translate("MainWindow", u"Vignette", None));  #"Redden" "Greenify" "Bloom Blue" "HDR" "Bass"
        ___qlistwidgetitem13 = self.listWidget.item(13)
        ___qlistwidgetitem13.setText(QCoreApplication.translate("MainWindow", u"Emboss", None)); 
        ___qlistwidgetitem14 = self.listWidget.item(14)
        ___qlistwidgetitem14.setText(QCoreApplication.translate("MainWindow", u"Redden", None));
        ___qlistwidgetitem15 = self.listWidget.item(15)
        ___qlistwidgetitem15.setText(QCoreApplication.translate("MainWindow", u"Greenify", None));
        ___qlistwidgetitem16 = self.listWidget.item(16)
        ___qlistwidgetitem16.setText(QCoreApplication.translate("MainWindow", u"Bloom Blue", None));
        ___qlistwidgetitem17 = self.listWidget.item(17)
        ___qlistwidgetitem17.setText(QCoreApplication.translate("MainWindow", u"HDR", None));
        ___qlistwidgetitem18 = self.listWidget.item(18)
        ___qlistwidgetitem18.setText(QCoreApplication.translate("MainWindow", u"Yellow", None));
        self.listWidget.setSortingEnabled(__sortingEnabled)

        self.label_2.setText(QCoreApplication.translate("MainWindow", u"<html><head/><body><p><span style=\" font-size:11pt;\">Amount%</span></p></body></html>", None))
        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"\u2705 ", None))
        self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"\u274c", None))
        self.pushButton_3.setText(QCoreApplication.translate("MainWindow", u"\u21a9\ufe0f", None))
        self.pushButton_4.setText(QCoreApplication.translate("MainWindow", u"Crop", None))
        self.pushButton_5.setText(QCoreApplication.translate("MainWindow", u"Resize", None))
        self.menuNew_File.setTitle(QCoreApplication.translate("MainWindow", u"File", None))
Exemple #3
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.")
Exemple #4
0
class FieldAttrsDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setLayout(QGridLayout())
        self.setWindowTitle("Edit Attributes")

        self.list_widget = QListWidget()
        self.list_widget.setMinimumSize(800, 600)
        self.add_button = QPushButton("Add attr")
        self.add_button.clicked.connect(self.__add_attr)
        self.remove_button = QPushButton("Remove attr")
        self.remove_button.clicked.connect(self._remove_attrs)

        self.layout().addWidget(self.list_widget, 0, 0, 2, 1)
        self.layout().addWidget(self.add_button, 0, 1)
        self.layout().addWidget(self.remove_button, 1, 1)

    def fill_existing_attrs(self, existing_dataset: Dataset):
        for attr in existing_dataset.attributes:
            if attr.name not in ATTRS_EXCLUDELIST:
                frame = FieldAttrFrame(attr)
                self._add_attr(existing_frame=frame)

    def __add_attr(self):
        """
        Only used for button presses. Any additional arguments from the signal are ignored.
        """
        self._add_attr()

    def _add_attr(self, existing_frame=None):
        item = QListWidgetItem()
        self.list_widget.addItem(item)
        frame = existing_frame if existing_frame is not None else FieldAttrFrame(
        )
        item.setSizeHint(frame.sizeHint())
        self._setup_attribute_name_validator(frame)
        self.list_widget.setItemWidget(item, frame)

    def _remove_attrs(self):
        for index in self.list_widget.selectedIndexes():
            self.list_widget.takeItem(index.row())

    def get_attrs(self):
        attrs_list = []
        for index in range(self.list_widget.count()):
            item = self.list_widget.item(index)
            widget = self.list_widget.itemWidget(item)
            if widget:
                attrs_list.append((widget.name, widget.value, widget.dtype))
        return attrs_list

    def get_attr_names(self):
        return [item[0] for item in self.get_attrs()]

    def _setup_attribute_name_validator(self, frame):
        frame.attr_name_lineedit.setValidator(
            AttributeNameValidator(self.get_attr_names))
        frame.attr_name_lineedit.validator().is_valid.connect(
            partial(
                validate_line_edit,
                frame.attr_name_lineedit,
                tooltip_on_accept="Attribute name is valid.",
                tooltip_on_reject="Attribute name is not valid",
            ))
Exemple #5
0
class Ui_Dialog(object):

    final_image = None

    def __init__(self, image):
        super().__init__()
        self.image = image

    def showFrame(self):
        if len(self.listWidget.selectedItems()) > 0:
            self.imageWidget.selectedMode = self.listWidget.selectedItems(
            )[0].text()
        else:
            self.imageWidget.selectedMode = None
        image = cv2.cvtColor(self.imageWidget.tempImage, cv2.COLOR_BGR2RGB)
        image = qimage2ndarray.array2qimage(image)
        self.imageWidget.setPixmap(QPixmap.fromImage(image))
        pass

    def commitCrop(self, Dialog):
        start = self.imageWidget.start
        end = self.imageWidget.current
        if start != end:
            print(start, end)
            #self.image=self.image[start[0]:end[0],start[1]:end[1]]
            self.image = self.image[start[1]:end[1], start[0]:end[0]]
            print(self.image.shape)
        Dialog.close()

    def cancle(self):
        #print("Lol")
        self.listWidget.setCurrentItem(None)
        self.imageWidget.tempImage = self.image

    def setupUi(self, Dialog):
        if not Dialog.objectName():
            Dialog.setObjectName(u"Dialog")
        Dialog.resize(1104, 481)

        self.pushButton_2 = QPushButton(Dialog)
        self.pushButton_2.setObjectName(u"pushButton_2")
        self.pushButton_2.setGeometry(QRect(970, 90, 61, 28))
        self.pushButton_2.clicked.connect(self.cancle)

        self.pushButton = QPushButton(Dialog)
        self.pushButton.setObjectName(u"pushButton")
        self.pushButton.setGeometry(QRect(880, 90, 61, 28))
        self.pushButton.clicked.connect(lambda: self.commitCrop(Dialog))

        self.listWidget = QListWidget(Dialog)
        QListWidgetItem(self.listWidget)
        QListWidgetItem(self.listWidget)
        QListWidgetItem(self.listWidget)
        QListWidgetItem(self.listWidget)
        QListWidgetItem(self.listWidget)
        QListWidgetItem(self.listWidget)
        QListWidgetItem(self.listWidget)
        self.listWidget.setObjectName(u"listWidget")
        self.listWidget.setGeometry(QRect(830, 150, 256, 192))
        """ self.label = QLabel(Dialog)
        self.label.setObjectName(u"label")
        self.label.setGeometry(QRect(20, 20, 781, 431))
        self.label.setStyleSheet(u"background-color: rgb(85, 255, 255)")
        self.label.setScaledContents(True) """
        self.imageWidget = ImageLable(Dialog, self.image)

        self.timer = QTimer()
        self.timer.timeout.connect(self.showFrame)
        self.timer.start(1)

        self.retranslateUi(Dialog)

        QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(
            QCoreApplication.translate("Dialog", u"Image Crop", None))
        self.pushButton_2.setText(
            QCoreApplication.translate("Dialog", u"\u274c", None))
        self.pushButton.setText(
            QCoreApplication.translate("Dialog", u"\u2705 ", None))

        __sortingEnabled = self.listWidget.isSortingEnabled()
        self.listWidget.setSortingEnabled(False)
        ___qlistwidgetitem = self.listWidget.item(0)
        ___qlistwidgetitem.setText(
            QCoreApplication.translate("Dialog", u"Free", None))
        ___qlistwidgetitem1 = self.listWidget.item(1)
        ___qlistwidgetitem1.setText(
            QCoreApplication.translate("Dialog", u"Square", None))
        ___qlistwidgetitem2 = self.listWidget.item(2)
        ___qlistwidgetitem2.setText(
            QCoreApplication.translate("Dialog", u"3:2", None))
        ___qlistwidgetitem3 = self.listWidget.item(3)
        ___qlistwidgetitem3.setText(
            QCoreApplication.translate("Dialog", u"4:3", None))
        ___qlistwidgetitem4 = self.listWidget.item(4)
        ___qlistwidgetitem4.setText(
            QCoreApplication.translate("Dialog", u"5:4", None))
        ___qlistwidgetitem5 = self.listWidget.item(5)
        ___qlistwidgetitem5.setText(
            QCoreApplication.translate("Dialog", u"7:5", None))
        ___qlistwidgetitem6 = self.listWidget.item(6)
        ___qlistwidgetitem6.setText(
            QCoreApplication.translate("Dialog", u"16:9", None))
        self.listWidget.setSortingEnabled(__sortingEnabled)
Exemple #6
0
class _ViewSwitcherWidget(QWidget):
    """Object that handles displaying of Enigma model wikis and images"""
    def __init__(self, master, regen_plug):
        """
        :param master: Qt parent object
        :param regen_plug: {callable} Regenerates settings view to new contents
        """
        super().__init__(master)

        layout = QHBoxLayout()
        self.setLayout(layout)

        # LIST OF AVAILABLE MODELS =============================================

        self.model_list = QListWidget()
        self.model_list.setMaximumWidth(150)
        self.model_list.setMinimumWidth(150)
        self.model_list.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        self.model_list.currentRowChanged.connect(self.select_model)

        self.regen_plug = regen_plug

        # STACKED MODEL VIEWS ==================================================

        self.stacked_wikis = QStackedWidget()
        for i, model in enumerate(VIEW_DATA):
            self.model_list.insertItem(i, model)
            description = VIEW_DATA[model]["description"]
            self.stacked_wikis.addWidget(
                _EnigmaViewWidget(self, model, description))
        self.total_models = len(VIEW_DATA)

        layout.addWidget(self.model_list)
        layout.addWidget(self.stacked_wikis)

        # Sets initially viewed
        self.currently_selected = None

    def select_model(self, i):
        """Called when the "Use this model" button is pressed
        :param i: {str} Newly selected model index
        """
        logging.info('Changing settings view to model "%s"' %
                     list(VIEW_DATA.keys())[i])
        model = list(VIEW_DATA.keys())[i]
        self.regen_plug(model)
        self.stacked_wikis.setCurrentIndex(i)

        self.model_list.blockSignals(True)
        self.model_list.setCurrentRow(i)
        self.model_list.blockSignals(False)

        self.currently_selected = model

    def highlight(self, i):
        """Highlights an option with Blue color, indicating that
        it is currently selected in EnigmaAPI
        :param i: {int} Index from list options
        """
        for index in range(self.total_models):
            item = self.model_list.item(index)
            item.setForeground(Qt.black)
            item.setToolTip(None)

        selected = self.model_list.item(i)
        selected.setBackground(Qt.gray)  # .setForeground(Qt.blue)
        selected.setToolTip("Currently used Enigma model")
Exemple #7
0
class Widget(QWidget):

    def __init__(self):
        QWidget.__init__(self)

        # Data for plotting and marker data storage
        self.data = {}
        self.slice_index = {
            'ind1': 0, 
            'ind2': 0
            }
        self.marker_id = 0
        self.marker_ind = []
        self.marker_setpoint = {
            'Marker1': 0, 
            'Marker2': 0, 
            }

        # Error message dialog widget
        self.error_popup = QErrorMessage()
        self.error_popup.setWindowTitle('Snap file error')

        # Left (List of Checkboxes)
        self.list_widget = QListWidget()
        #Resize width and height
        self.list_widget.setSizePolicy(QSizePolicy.Preferred, 
                                       QSizePolicy.Preferred)
        self.list_widget.setMinimumWidth(200)
        self.list_widget.setMaximumWidth(400)
        # self.list_widget.setMinimumHeight(300)
        self.list_widget.setMaximumHeight(500)

        # Signal groupbox
        self.signal_groupbox = QGroupBox('Available Signals')
        self.signal_groupbox.setMinimumWidth(200)
        self.signal_groupbox.setMaximumWidth(350)
        self.signal_groupbox.setMinimumHeight(100)
        self.sig_group_layout = QVBoxLayout()
        self.signal_groupbox.setLayout(self.sig_group_layout)
        # Statistics groupbox
        self.stats_groupbox = QGroupBox('Statistics')
        self.stats_groupbox.setMinimumWidth(200)
        self.stats_groupbox.setMaximumWidth(350)
        self.stats_groupbox.setMinimumHeight(240)
        self.stats_group_layout = QFormLayout()

        # Label initiation
        # Marker Time 1
        self.mark_one_time_label = QLabel('Marker1_time: ')
        self.mark_one_time_value = QLabel()
        # Marker Time 2
        self.mark_two_time_label = QLabel('Marker2_time: ')
        self.mark_two_time_value = QLabel()
        # On/Off labels for 0/1 signals counter
        self.on_off_label = QLabel('On/Off: ')
        self.on_off_value = QLabel()
        # Mean value
        self.mean_label = QLabel('Mean: ')
        self.mean_value = QLabel()
        # Standard deviation
        self.std_label = QLabel('Sigma(STD): ')
        self.std_value = QLabel()
        # Minimal value
        self.min_label = QLabel('Min: ')
        self.min_value = QLabel()
        # Maximual value
        self.max_label = QLabel('Max: ')
        self.max_value = QLabel()
        # Max - Min value
        self.val_diff_label = QLabel('Max-Min: ')
        self.val_diff_value = QLabel()
        # Time difference (X-axis)
        self.time_diff_label = QLabel('Time_diff: ')
        self.time_diff_value = QLabel('')

        # Row addition of labels
        self.stats_group_layout.addRow(self.mark_one_time_label, 
                                       self.mark_one_time_value)
        self.stats_group_layout.addRow(self.mark_two_time_label,
                                       self.mark_two_time_value)
        self.stats_group_layout.addRow(self.time_diff_label, 
                                       self.time_diff_value)
        self.stats_group_layout.addRow(self.on_off_label, self.on_off_value)
        self.stats_group_layout.addRow(self.mean_label, self.mean_value)
        self.stats_group_layout.addRow(self.std_label, self.std_value)
        self.stats_group_layout.addRow(self.min_label, self.min_value)
        self.stats_group_layout.addRow(self.max_label, self.max_value)
        self.stats_group_layout.addRow(self.val_diff_label, 
                                       self.val_diff_value)
        self.stats_groupbox.setLayout(self.stats_group_layout)

        # Set markers section of the application (bottom left)
        self.marker_grid = QGridLayout()
        self.marker_one_notice = QLabel()
        self.marker_two_notice = QLabel()
        self.set_marker_one_label = QLabel('Set Marker1:')
        self.set_marker_two_label = QLabel('Set Marker2:')
        self.set_marker_one_value = QLineEdit()
        self.set_marker_one_value.setMaximumWidth(100)
        self.set_marker_two_value = QLineEdit()
        self.set_marker_two_value.setMaximumWidth(100)

        self.marker_grid.addWidget(self.set_marker_one_label)
        self.marker_grid.addWidget(self.set_marker_one_value)
        self.marker_grid.addWidget(self.marker_one_notice)
        self.marker_grid.addWidget(self.set_marker_two_label)
        self.marker_grid.addWidget(self.set_marker_two_value)
        self.marker_grid.addWidget(self.marker_two_notice)
                                        
        # Leftside app layout
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.list_widget)
        self.v_layout.addWidget(self.signal_groupbox)
        self.v_layout.addWidget(self.stats_groupbox)
        self.v_layout.addLayout(self.marker_grid)

        # Matplotlib figure
        self.fig = Figure(figsize=(5, 3))
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setSizePolicy(QSizePolicy.Expanding, 
                                  QSizePolicy.Expanding)
        self.ax = self.canvas.figure.subplots()
        self.ax.grid()
        self.ax.set_xlabel('Time[s]')
        self.fig.suptitle('Parameter Plot')
      
        # QWidget Layout
        self.h_layout = QHBoxLayout()
        self.h_layout.addLayout(self.v_layout)
        self.h_layout.addWidget(self.canvas)

        # Set the layout to the QWidget
        self.setLayout(self.h_layout)

        # ListWidget and plot connections
        self.list_widget.itemChanged.connect(self.item_changed)
        self.click_event = self.fig.canvas.mpl_connect('button_press_event',
                                                       self.on_click)
        self.set_marker_one_value.returnPressed.connect(
                                                lambda: self.add_marker('one'))
        self.set_marker_two_value.returnPressed.connect(
                                                lambda: self.add_marker('two'))
        
    # Add radio button when signal is checked for plotting
    def add_radio_button(self, name):
        self.rad_btn = QRadioButton(name)
        self.rad_btn.toggled.connect(self.calculate_signal_stats)
        self.sig_group_layout.addWidget(self.rad_btn)

    # Remove radio button when signal is unchecked for plotting
    def remove_radio_button(self, name):
        for item in self.signal_groupbox.children():
            try:
                if item.text() == name:
                    item.setParent(None)
            except AttributeError:
                pass
    
    # Remove all radiobuttons on new data load
    def clear_signals(self):
        count = 0
        for item in self.signal_groupbox.children():
            if count == 0:
                count = 1
                continue 
            else:
                item.setParent(None)  
    # Check state of all radiobuttons, if none is checked remove stats values
    def check_signals(self):
        count = 0
        num_of_check = 0
        for item in self.signal_groupbox.children():
            if count == 0:
                count = 1
                continue 
            else:
                if item.isChecked():
                    num_of_check += 1
        # If no radiobuttons are checked, remove stats
        if num_of_check == 0:
            self.mean_value.setText('') 
            self.std_value.setText('') 
            self.max_value.setText('') 
            self.min_value.setText('') 
            self.val_diff_value.setText('') 
            self.on_off_value.setText('')               

    # Item additon of listWidget
    def fill_list(self, list_items):
        self.list_widget.clear()

        for column in list_items:
            item = QListWidgetItem(column)
            item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)
            self.list_widget.addItem(item)

        self.show()
    
    # If new data is loaded, replace the old one
    def replace_data(self, temp):
        if not temp == self.data:
            self.data = temp
            self.clear_signals()

    @Slot()
    # Item state changed in listWidget event handler
    def item_changed(self, item):
        if item.checkState() == Qt.Unchecked:
           self.remove_plot(item.text())
           self.remove_radio_button(item.text())
           self.check_signals()
        else:
            self.add_plot(self.data['Time'], 
                          self.data[item.text()], item.text())
            self.add_radio_button(item.text())
                
    # Method for plotting data
    def add_plot(self, x_data, y_data, name):
        self.ax.plot(x_data, y_data, label=name, picker=3)
        self.ax.grid(True)
        self.ax.relim()
        self.ax.set_xlabel('Time[s]')
        self.ax.autoscale_view()
        self.ax.legend(loc='upper right')
        self.canvas.draw()

    # Method for marker addition via QLineEdit
    def add_marker(self, label):
        # Check if any signal is plotted
        sig_count = 0
        for i in range(self.list_widget.count()):
            if self.list_widget.item(i).checkState() == Qt.Checked:
                sig_count += 1

        if sig_count == 0:
            self.marker_one_notice.setText('No active signal!')
            self.marker_two_notice.setText('No active signal!')
            return
        try:
            max_time = self.data['Time'][-1]
            min_time = self.data['Time'][0]
        except KeyError:
            self.marker_one_notice.setText('Signal data not loaded!')
            self.marker_two_notice.setText('Signal data not loaded!')
        if label == 'one':
            try:
                mark1_value = float(self.set_marker_one_value.text())
                if mark1_value < max_time and mark1_value > min_time:
                    if self.marker_id == 0:
                        self.marker_id += 1
                        label_id = self.marker_id
                    elif self.marker_id == 1:
                        self.marker_id += 1
                        label_id = self.marker_id
                        self.remove_marker('first')
                    else:
                        self.remove_marker('first')
                        label_id = 1

                    self.marker_one_notice.setText('')
                    self.marker_setpoint['Marker1'] = mark1_value
                    self.mark_one_time_value.setText(
                                            self.set_marker_one_value.text())
                    self.calculate_marker_stats()
                    self.calculate_signal_stats()
                    
                    # Draw the marker
                    L =  self.ax.axvline(
                                    x=float(self.set_marker_one_value.text()), 
                                    linestyle='dashed', 
                                    color='red', 
                                    label='_Marker' + str(label_id))
                    self.fig.canvas.draw()
                else:
                    self.marker_one_notice.setText('Marker1 out of bounds')
            except ValueError:
                self.marker_one_notice.setText('Non-Valid value entered!')
        else:
            try:
                mark2_value = float(self.set_marker_two_value.text()) 
                if mark2_value < max_time and mark2_value > min_time:
                    if self.marker_id == 1:
                        self.marker_id += 1
                        label_id = self.marker_id
                    elif self.marker_id == 2:
                        label_id = 2
                        self.remove_marker('second')
                    else:
                        self.marker_two_notice.setText('Marker1 not placed')
                    self.marker_two_notice.setText('')
                    self.marker_setpoint['Marker2'] = mark2_value
                    self.mark_two_time_value.setText(
                                            self.set_marker_two_value.text())
                    self.calculate_marker_stats()
                    self.calculate_signal_stats()
                    # Draw the marker
                    L =  self.ax.axvline(
                                    x=float(self.set_marker_two_value.text()), 
                                    linestyle='dashed', 
                                    color='red', 
                                    label='_Marker' + str(label_id))
                    self.fig.canvas.draw()
                else:
                    self.marker_two_notice.setText('Marker2 out of bounds')
            except:
                self.marker_two_notice.setText('Non-Valid value entered!')
    
    # Marker removal method
    def remove_marker(self, label):
        for item in self.ax.lines:
            if 'Marker' in item.get_label():
                self.marker_ind.append(item)

        # If there are two markers remove them from plot and adjust marker
        # time labels
        if label == 'both':
            self.marker_ind[0].remove()
            self.marker_ind[1].remove()
            self.marker_ind = []
            self.marker_setpoint['Marker1'] = 0
            self.marker_setpoint['Marker2'] = 0
            self.mark_one_time_value.setText('')
            self.mark_two_time_value.setText('')
            self.time_diff_value.setText('')
            self.marker_id = 0
        # Remove only marker1
        elif label == 'first':
            self.marker_ind[0].remove()
            self.marker_ind = []
            self.marker_setpoint['Marker1'] = 0
            self.mark_one_time_value.setText('')
            self.marker_id -= 1
        elif label == 'second':
            self.marker_ind[1].remove()
            self.marker_ind = []
            self.marker_setpoint['Marker2'] = 0
            self.mark_two_time_value.setText('')
            self.marker_id -= 1

        self.ax.set_xlabel('Time[s]')
        self.canvas.draw()
    
    # Method for plot removal
    def remove_plot(self, name):
        cnt = 0
        for item in self.ax.lines:
            if item.get_label() == name:
                self.ax.lines[cnt].remove()
            cnt += 1
        self.ax.relim()
        self.ax.autoscale_view()
        self.ax.legend(loc='upper right')
        self.ax.set_xlabel('Time[s]')
        self.canvas.draw()

        # Check if all elements are unticked
        counter = 0
        for i in range(self.list_widget.count()):
            if self.list_widget.item(i).checkState() == Qt.Checked:
                counter +=1
        if counter == 0:
            self.remove_marker('both')
            
    # On click event for plot, only two markers can be active at the time
    def on_click(self, event):
        try:
            # Catch left click event
            if event.button == 1:
                x = event.xdata
                if self.marker_id < 2:
                    if self.marker_id == 0:
                        self.marker_setpoint['Marker1'] = round(x)
                        self.mark_one_time_value.setText(
                                            str(self.marker_setpoint['Marker1']))
                        self.calculate_marker_stats()
                        self.calculate_signal_stats()
                    else:
                        self.marker_setpoint['Marker2'] = round(x)
                        self.mark_two_time_value.setText(
                                            str(self.marker_setpoint['Marker2']))
                        self.calculate_marker_stats()
                        self.calculate_signal_stats()
                    self.marker_id += 1
                    L =  self.ax.axvline(x=x, 
                                        linestyle='dashed', 
                                        color='red', 
                                        label='_Marker' + str(self.marker_id))
                    self.fig.canvas.draw()
            # Catch right click event
            elif event.button == 3:
                self.remove_marker('both')
        except TypeError:
            pass
    # Marker analysis method
    def calculate_marker_stats(self):
        if self.marker_setpoint['Marker2'] == 0:
            diff = self.data['Time'][-1] - self.marker_setpoint['Marker1']
            self.time_diff_value.setText(str(diff))
        else:
            diff = self.marker_setpoint['Marker2'] -  \
                   self.marker_setpoint['Marker1']
            
            self.time_diff_value.setText(convert_seconds(diff))
    # Signal analysis method
    def calculate_signal_stats(self):
        self.check_signals()
        selected_signal = ''
        signal_data = []
        num_off, num_on = 0, 0
        for item in self.signal_groupbox.children():
            try:
                if item.isChecked():
                    # Signal extraction block
                    selected_signal = item.text()
                    # If only one marker, Marker1 is placed on graph
                    if self.marker_setpoint['Marker2'] == 0 and self.marker_setpoint['Marker1'] != 0:
                        for i in range(len(self.data['Time'])):
                            if self.data['Time'][i] > self.marker_setpoint['Marker1']:
                                self.slice_index['ind1'] = i
                                break
                        signal_data = np.asarray(
                        self.data[selected_signal][self.slice_index['ind1']:], 
                                    dtype=np.float32)
                    # Both markers, Marker1 and Marker2 are present on graph
                    elif self.marker_setpoint['Marker1'] != 0 and self.marker_setpoint['Marker2'] != 0:
                        for i in range(len(self.data['Time'])):
                            if self.data['Time'][i] > self.marker_setpoint['Marker1']:
                                self.slice_index['ind1'] = i
                                break
                        for i in range(len(self.data['Time'])):
                            if self.data['Time'][len(self.data['Time']) - i - 1] < self.marker_setpoint['Marker2']:
                                self.slice_index['ind2'] = len(self.data['Time']) - i
                                break
                        signal_data = np.asarray(
                        self.data[selected_signal][self.slice_index['ind1']:self.slice_index['ind2'] - 1], 
                                                    dtype=np.float32)
                        
                    # No markers present, whole signal stats are showed
                    else:
                        signal_data = np.asarray(self.data[selected_signal], 
                                                    dtype=np.float32)
                    try:
                        # Signal mean calculation
                        self.mean_value.setText(str(np.mean(signal_data)))
                        # Standard deviation
                        self.std_value.setText(str(np.std(signal_data)))
                        # Maximum value
                        self.max_value.setText(str(np.max(signal_data)))
                        # Minimum value
                        self.min_value.setText(str(np.min(signal_data)))
                        # Max - Min
                        self.val_diff_value.setText(str(np.max(signal_data) - 
                                                    (np.min(signal_data))))
                        if np.max(signal_data) == 1.0:
                            for i in range(len(signal_data)):
                                if i != len(signal_data) - 1:
                                    temp = signal_data[i] - signal_data[i+1]
                                    if temp == 1:
                                        num_off += 1
                                    elif temp == -1:
                                        num_on += 1
                            self.on_off_value.setText(str(num_on) + 
                                                    '\\' + str(num_off))
                    except ValueError:
                        err_line1 = 'Missing data, result is empty array!'
                        err_line2 = '\n Please check snap file.' 
                        self.error_popup.showMessage(err_line1 + err_line2)
            except AttributeError:
                pass
Exemple #8
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()
Exemple #9
0
class PiecesPlayer(QWidget):
    """ main widget of application (used as widget inside PiecesMainWindow) """
    def __init__(self, parent):
        """ standard constructor: set up class variables, ui elements
            and layout """

        # TODO: split current piece info into separate lineedits for title, album name and length
        # TODO: make time changeable by clicking next to the slider (not only
        #       by dragging the slider)
        # TODO: add "about" action to open info dialog in new "help" menu
        # TODO: add option to loop current piece (?)
        # TODO: more documentation
        # TODO: add some "whole piece time remaining" indicator? (complicated)
        # TODO: implement a playlist of pieces that can be edited and enable
        #       going back to the previous piece (also un- and re-shuffling?)
        # TODO: implement debug dialog as menu action (if needed)

        if not isinstance(parent, PiecesMainWindow):
            raise ValueError('Parent widget must be a PiecesMainWindow')

        super(PiecesPlayer, self).__init__(parent=parent)

        # -- declare and setup variables for storing information --
        # various data
        self._set_str = ''  # string of currently loaded directory sets
        self._pieces = {}  # {<piece1>: [<files piece1 consists of>], ...}
        self._playlist = []  # list of keys of self._pieces (determines order)
        self._shuffled = True  # needed for (maybe) reshuffling when looping
        # doc for self._history:
        # key: timestamp ('HH:MM:SS'),
        # value: info_str of piece that started playing at that time
        self._history = {}
        self._status = 'Paused'
        self._current_piece = {'title': '', 'files': [], 'play_next': 0}
        self._default_volume = 60  # in percent from 0 - 100
        self._volume_before_muted = self._default_volume
        # set to true by self.__event_movement_ended and used by self.__update
        self._skip_to_next = False
        # vlc-related variables
        self._vlc_instance = VLCInstance()
        self._vlc_mediaplayer = self._vlc_instance.media_player_new()
        self._vlc_mediaplayer.audio_set_volume(self._default_volume)
        self._vlc_medium = None
        self._vlc_events = self._vlc_mediaplayer.event_manager()

        # -- create and setup ui elements --
        # buttons
        self._btn_play_pause = QPushButton(QIcon(get_icon_path('play')), '')
        self._btn_previous = QPushButton(QIcon(get_icon_path('previous')), '')
        self._btn_next = QPushButton(QIcon(get_icon_path('next')), '')
        self._btn_volume = QPushButton(QIcon(get_icon_path('volume-high')), '')
        self._btn_loop = QPushButton(QIcon(get_icon_path('loop')), '')
        self._btn_loop.setCheckable(True)
        self._btn_play_pause.clicked.connect(self.__action_play_pause)
        self._btn_previous.clicked.connect(self.__action_previous)
        self._btn_next.clicked.connect(self.__action_next)
        self._btn_volume.clicked.connect(self.__action_volume_clicked)
        # labels
        self._lbl_current_piece = QLabel('Current piece:')
        self._lbl_movements = QLabel('Movements:')
        self._lbl_time_played = QLabel('00:00')
        self._lbl_time_left = QLabel('-00:00')
        self._lbl_volume = QLabel('100%')
        # needed so that everything has the same position
        # independent of the number of digits of volume
        self._lbl_volume.setMinimumWidth(55)
        # sliders
        self._slider_time = QSlider(Qt.Horizontal)
        self._slider_volume = QSlider(Qt.Horizontal)
        self._slider_time.sliderReleased.connect(
            self.__event_time_changed_by_user)
        self._slider_volume.valueChanged.connect(self.__event_volume_changed)
        self._slider_time.setRange(0, 100)
        self._slider_volume.setRange(0, 100)
        self._slider_volume.setValue(self._default_volume)
        self._slider_volume.setMinimumWidth(100)
        # other elements
        self._checkbox_loop_playlist = QCheckBox('Loop playlist')
        self._lineedit_current_piece = QLineEdit()
        self._lineedit_current_piece.setReadOnly(True)
        self._lineedit_current_piece.textChanged.connect(
            self.__event_piece_text_changed)
        self._listwidget_movements = QListWidget()
        self._listwidget_movements.itemClicked.connect(
            self.__event_movement_selected)

        # -- create layout and insert ui elements--
        self._layout = QVBoxLayout(self)
        # row 0 (name of current piece)
        self._layout_piece_name = QHBoxLayout()
        self._layout_piece_name.addWidget(self._lbl_current_piece)
        self._layout_piece_name.addWidget(self._lineedit_current_piece)
        self._layout.addLayout(self._layout_piece_name)
        # rows 1 - 5 (movements of current piece)
        self._layout.addWidget(self._lbl_movements)
        self._layout.addWidget(self._listwidget_movements)
        # row 6 (time)
        self._layout_time = QHBoxLayout()
        self._layout_time.addWidget(self._lbl_time_played)
        self._layout_time.addWidget(self._slider_time)
        self._layout_time.addWidget(self._lbl_time_left)
        self._layout.addLayout(self._layout_time)
        # row 7 (buttons and volume)
        self._layout_buttons_and_volume = QHBoxLayout()
        self._layout_buttons_and_volume.addWidget(self._btn_play_pause)
        self._layout_buttons_and_volume.addWidget(self._btn_previous)
        self._layout_buttons_and_volume.addWidget(self._btn_next)
        self._layout_buttons_and_volume.addWidget(self._btn_loop)
        self._layout_buttons_and_volume.addSpacing(40)
        # distance between loop and volume buttons: min. 40, but stretchable
        self._layout_buttons_and_volume.addStretch()
        self._layout_buttons_and_volume.addWidget(self._btn_volume)
        self._layout_buttons_and_volume.addWidget(self._slider_volume)
        self._layout_buttons_and_volume.addWidget(self._lbl_volume)
        self._layout.addLayout(self._layout_buttons_and_volume)

        # -- setup hotkeys --
        self._KEY_CODES_PLAY_PAUSE = [269025044]
        self._KEY_CODES_NEXT = [269025047]
        self._KEY_CODES_PREVIOUS = [269025046]
        self._keyboard_listener = keyboard.Listener(on_press=self.__on_press)
        self._keyboard_listener.start()
        QShortcut(QKeySequence('Space'), self, self.__action_play_pause)

        # -- various setup --
        self._timer = QTimer(self)
        self._timer.timeout.connect(self.__update)
        self._timer.start(100)  # update every 100ms
        self.setMinimumWidth(900)
        self.setMinimumHeight(400)
        # get directory set(s) input and set up self._pieces
        # (exec_ means we'll wait for the user input before continuing)
        DirectorySetChooseDialog(self, self.set_pieces_and_playlist).exec_()
        # skip to next movement / next piece when current one has ended
        self._vlc_events.event_attach(VLCEventType.MediaPlayerEndReached,
                                      self.__event_movement_ended)

    def __action_next(self):
        """ switches to next file in self._current_piece['files']
            or to the next piece, if the current piece has ended """

        reset_pause_after_current = False

        # current movement is last of the current piece
        if self._current_piece['play_next'] == -1:
            if len(self._playlist) == 0:  # reached end of playlist
                if self._btn_loop.isChecked():
                    self._playlist = list(self._pieces.keys())
                    if self._shuffled:
                        shuffle(self._playlist)
                    return

                if self._status == 'Playing':
                    self.__action_play_pause()
                self._current_piece['title'] = ''
                self._current_piece['files'] = []
                self._current_piece['play_next'] = -1
                self._lineedit_current_piece.setText('')
                self.__update_movement_list()
                self.parentWidget().update_status_bar(
                    self._status, 'End of playlist reached.')
                return
            else:
                if self.parentWidget().get_exit_after_current():
                    self.parentWidget().exit()
                if self.parentWidget().get_pause_after_current():
                    self.__action_play_pause()
                    reset_pause_after_current = True
                    # reset of the menu action will be at the end of this
                    # function, or else we won't stay paused

                self._current_piece['title'] = self._playlist.pop(0)
                self._current_piece['files'] = [
                    p[1:-1] for p in self._pieces[self._current_piece['title']]
                ]
                # some pieces only have one movement
                self._current_piece['play_next'] = \
                    1 if len(self._current_piece['files']) > 1 else -1
                self.__update_vlc_medium(0)
                self._lineedit_current_piece.setText(
                    create_info_str(self._current_piece['title'],
                                    self._current_piece['files']))
                self.__update_movement_list()
                self._history[datetime.now().strftime('%H:%M:%S')] = \
                    self._lineedit_current_piece.text()
        else:
            self.__update_vlc_medium(self._current_piece['play_next'])
            # next is last movement
            if self._current_piece['play_next'] == \
               len(self._current_piece['files']) - 1:
                self._current_piece['play_next'] = -1
            else:  # there are at least two movements of current piece left
                self._current_piece['play_next'] += 1
        if self._status == 'Paused' and not reset_pause_after_current:
            self.__action_play_pause()
        elif reset_pause_after_current:
            self.parentWidget().set_pause_after_current(False)
        else:
            self._vlc_mediaplayer.play()
        self.parentWidget().update_status_bar(
            self._status,
            f'{len(self._pieces) - len(self._playlist)}/{len(self._pieces)}')

    def __action_play_pause(self):
        """ (gets called when self._btn_play_pause is clicked)
            toggles playing/pausing music and updates everything as needed """

        # don't do anything now (maybe end of playlist reached?)
        if self._current_piece['title'] == '':
            return

        if self._status == 'Paused':
            if not self._vlc_medium:
                self.__action_next()
            self._vlc_mediaplayer.play()
            self._btn_play_pause.setIcon(QIcon(get_icon_path('pause')))
            self._status = 'Playing'
        else:
            self._vlc_mediaplayer.pause()
            self._btn_play_pause.setIcon(QIcon(get_icon_path('play')))
            self._status = 'Paused'
        self.parentWidget().update_status_bar(
            self._status,
            f'{len(self._pieces) - len(self._playlist)}/{len(self._pieces)}')

    def __action_previous(self):
        """ (called when self._btn_previous ist clicked)
            goes back one movement of the current piece, if possible
            (cannot go back to previous piece) """

        # can't go back to previous piece, but current one has no or one movement
        if len(self._current_piece['files']) <= 1:
            pass
        # currently playing first movement, so nothing to do as well
        elif self._current_piece['play_next'] == 1:
            pass
        else:  # we can go back one movement
            # currently at last movement
            if self._current_piece['play_next'] == -1:
                # set play_next to last movement
                self._current_piece['play_next'] = \
                    len(self._current_piece['files']) - 1
            else:  # currently before last movement
                # set play_next to current movement
                self._current_piece['play_next'] -= 1
            self._vlc_mediaplayer.stop()
            self.__update_vlc_medium(self._current_piece['play_next'] - 1)
            self._vlc_mediaplayer.play()

    def __action_volume_clicked(self):
        """ (called when self._btn_volume is clicked)
            (un)mutes volume """

        if self._slider_volume.value() == 0:  # unmute volume
            self._slider_volume.setValue(self._volume_before_muted)
        else:  # mute volume
            self._volume_before_muted = self._slider_volume.value()
            self._slider_volume.setValue(0)

    def __event_movement_ended(self, event):
        """ (called when self._vlc_media_player emits a MediaPlayerEndReached
            event)
            sets self._skip_to_next to True so the next self.__update call
            will trigger self.__action_next """

        self._skip_to_next = True

    def __event_movement_selected(self):
        """ (called when self._listwidget_movements emits itemClicked)
            skips to the newly selected movement """

        index = self._listwidget_movements.indexFromItem(
            self._listwidget_movements.currentItem()).row()
        # user selected a movement different from the current one
        if index != self.__get_current_movement_index():
            self._current_piece['play_next'] = index
            self.__action_next()

    def __event_piece_text_changed(self):
        """ (called when self._lineedit_current_piece emits textChanged)
            ensures that the user sees the beginning of the text in
            self._lineedit_current_piece (if text is too long, the end will be
            cut off and the user must scroll manually to see it) """

        self._lineedit_current_piece.setCursorPosition(0)

    def __event_volume_changed(self):
        """ (called when value of self._slider_volume changes)
            updates text of self._lbl_volume to new value of self._slider_value
            and sets icon of self._btn_volume to a fitting one """

        volume = self._slider_volume.value()
        self._lbl_volume.setText(f'{volume}%')
        if volume == 0:
            self._btn_volume.setIcon(QIcon(get_icon_path('volume-muted')))
        elif volume < 34:
            self._btn_volume.setIcon(QIcon(get_icon_path('volume-low')))
        elif volume < 67:
            self._btn_volume.setIcon(QIcon(get_icon_path('volume-medium')))
        else:
            self._btn_volume.setIcon(QIcon(get_icon_path('volume-high')))
        self._vlc_mediaplayer.audio_set_volume(volume)

    def __event_time_changed_by_user(self):
        """ (called when user releases self._slider_time)
            synchronizes self._vlc_mediaplayer's position to the new value
            of self._slider_time """

        self._vlc_mediaplayer.set_position(self._slider_time.value() / 100)

    def __get_current_movement_index(self):
        """ returns the index of the current movement in
            self._current_piece['files'] """

        play_next = self._current_piece['play_next']
        if play_next == -1:
            return len(self._current_piece['files']) - 1
        else:
            return play_next - 1

    def __on_press(self, key):
        """ (called by self._keyboard_listener when a key is pressed)
            looks up key code corresponding to key and calls the appropriate
            action function """

        try:  # key is not always of the same type (why would it be?!)
            key_code = key.vk
        except AttributeError:
            key_code = key.value.vk
        if key_code in self._KEY_CODES_PLAY_PAUSE:
            self.__action_play_pause()
        elif key_code in self._KEY_CODES_NEXT:
            self.__action_next()
        elif key_code in self._KEY_CODES_PREVIOUS:
            self.__action_previous()

    def __update_movement_list(self):
        """ removes all items currently in self._listwidget_movements and adds
            everything in self._current_piece['files] """

        # TODO: use ID3 title instead of filename

        while self._listwidget_movements.count() > 0:
            self._listwidget_movements.takeItem(0)
        files = self._current_piece['files']
        if os_name == 'nt':  # windows paths look different than posix paths
            # remove path to file, title number and .mp3 ending
            files = [i[i.rfind('\\') + 3:-4] for i in files]
        else:
            files = [i[i.rfind('/') + 4:-4] for i in files]
        self._listwidget_movements.addItems(files)

    def __update(self):
        """ (periodically called when self._timer emits timeout signal)
            updates various ui elements"""

        # -- select currently playing movement in self._listwidget_movements --
        if self._listwidget_movements.count() > 0:
            self._listwidget_movements.item(
                self.__get_current_movement_index()).setSelected(True)

        # -- update text of self._lbl_time_played and self._lbl_time_left,
        # if necessary --
        if self._vlc_medium:
            try:
                time_played = self._vlc_mediaplayer.get_time()
                medium_duration = self._vlc_medium.get_duration()
                # other values don't make sense (but do occur)
                if (time_played >= 0) and (time_played <= medium_duration):
                    self._lbl_time_played.setText(
                        get_time_str_from_ms(time_played))
                else:
                    self._lbl_time_played.setText(get_time_str_from_ms(0))
                self._lbl_time_left.setText(
                    f'-{get_time_str_from_ms(medium_duration - time_played)}')
            except OSError:  # don't know why that occurs sometimes
                pass

        # -- update value of self._slider_time --
        # don't reset slider to current position if user is dragging it
        if not self._slider_time.isSliderDown():
            try:
                self._slider_time.setValue(
                    self._vlc_mediaplayer.get_position() * 100)
            except OSError:  # don't know why that occurs sometimes
                pass

        if self._skip_to_next:
            self._skip_to_next = False
            self.__action_next()

    def __update_vlc_medium(self, files_index):
        old_medium = self._vlc_medium
        self._vlc_medium = self._vlc_instance.media_new(
            self._current_piece['files'][files_index])
        self._vlc_medium.parse()
        self._vlc_mediaplayer.set_media(self._vlc_medium)
        if old_medium:  # only release if not None
            old_medium.release()

    def get_history(self):
        """ getter function for parent widget """

        return self._history

    def get_set_str(self):
        """ getter function for parent widget """

        return self._set_str if self._set_str != '' \
            else 'No directory set loaded.'

    def set_pieces_and_playlist(self, pieces, playlist, set_str, shuffled):
        """ needed so that DirectorySetChooseDialog can set our self._pieces
            and self._playlist """

        # just to be sure
        if isinstance(pieces, dict) and isinstance(playlist, list):
            self._vlc_mediaplayer.stop()
            self._set_str = set_str
            self._pieces = pieces
            self._playlist = playlist
            self._shuffled = shuffled
            self._current_piece['title'] = self._playlist.pop(0)
            self._current_piece['files'] = [
                p.replace('"', '')
                for p in self._pieces[self._current_piece['title']]
            ]
            self._current_piece['play_next'] = \
                1 if len(self._current_piece['files']) > 1 else -1
            self._lineedit_current_piece.setText(
                create_info_str(self._current_piece['title'],
                                self._current_piece['files']))
            self.__update_movement_list()
            self.__update_vlc_medium(0)
            self._history[datetime.now().strftime('%H:%M:%S')] = \
                self._lineedit_current_piece.text()

    def exit(self):
        """ exits cleanly """

        try:  # don't know why that occurs sometimes
            self._vlc_mediaplayer.stop()
            self._vlc_mediaplayer.release()
            self._vlc_instance.release()
        except OSError:
            pass

        self._keyboard_listener.stop()
Exemple #10
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))
Exemple #11
0
class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Network Designer")
        self.setGeometry(300, 200, 840, 720)
        self.current_id = 1
        self.createLayout()

        self.couple = []
        self.show()

    def makeButtonsLayout(self):
        self.button = QPushButton("Add Node", self)
        self.button.clicked.connect(self.addNode)

        self.btn_connection = QPushButton("Add Connection:", self)
        self.btn_connection.clicked.connect(self.addConnection)

        self.button3 = QPushButton("Export Network", self)
        self.button3.clicked.connect(self.file_save)

        self.lbl_connection = QLabel("Connection")

        self.l_btns = QHBoxLayout()
        self.l_btns.addWidget(self.button3)
        self.l_btns.addStretch()
        self.l_btns.addWidget(self.btn_connection)
        self.l_btns.addWidget(self.lbl_connection)
        self.l_btns.addStretch()
        self.l_btns.addWidget(self.button)
        self.btns = QWidget()
        self.btns.setLayout(self.l_btns)
        self.btns.setFixedHeight(40)

    def initializeGview(self):
        self.scene = GraphicsScene()
        self.scene.setSceneRect(0, 0, 480, 480)
        self.scene.click.connect(self.keepNode)
        self.addNode()
        self.view = QGraphicsView(self.scene)
        self.view.setGeometry(0, 0, 500, 500)
        self.view.scale(1, 1)

    def createOrderList(self):
        self.orderList = QListWidget()
        # Enable drag & drop ordering of items.
        self.orderList.setDragDropMode(QAbstractItemView.InternalMove)

    def createLayout(self):
        self.makeButtonsLayout()
        self.initializeGview()
        self.createOrderList()

        l_network = QHBoxLayout()
        l_network.addWidget(self.view)
        l_network.addStretch()
        l_network.addWidget(self.orderList)

        self.l_root = QVBoxLayout()
        self.l_root.addLayout(l_network)
        self.l_root.addStretch()
        self.l_root.addWidget(self.btns)

        # self.l_root.addWidget(self.view)
        self.setLayout(self.l_root)

    def addNode(self):
        greenBrush = QBrush(Qt.green)
        blackPen = QPen(Qt.black)
        # blueBrush = QBrush(Qt.blue)

        blackPen.setWidth(5)
        ellipse = GraphicsEllipse(str(self.current_id), blackPen, greenBrush, 100, 100, NODE_D, NODE_D)
        self.scene.addItem(ellipse)
        self.current_id += 1

    def keepNode(self, node):
        if len(self.couple) < 2:
            self.couple.append(node)
        else:
            self.couple.pop(0)
            self.couple.append(node)
        if len(self.couple) == 2:
            self.lbl_connection.setText(self.couple[0].label + " --> " + self.couple[1].label)

    def addConnection(self):
        line = GraphicsLine(self.couple[0], self.couple[1], NODE_R)
        self.scene.addItem(line)

        for v in self.couple:
            v.add_connection(line)
        self.orderList.addItem(self.lbl_connection.text())

    def getNodes(self):
        positions = {}
        for i in self.scene.items():
            if type(i) is GraphicsEllipse:
                positions[int(i.label)] = i.getPosition()
        return positions

    def getConnections(self):
        connections = []
        for i in range(self.orderList.count()):
            conn = self.orderList.item(i).text().split(" --> ")
            connections.append((int(conn[0]), int(conn[1]), {"label": str(i + 1)}))
        return connections

    def file_save(self):
        positions = self.getNodes()
        connections = self.getConnections()
        network = {}
        network["labels"] = {i: i for i in sorted(list(positions.keys()))}
        network["edges"] = connections
        network["pos"] = positions
        text = json.dumps(network)
        name = QFileDialog.getSaveFileName(self, 'Save File')
        file = open(name[0], 'w')
        # text = "something"
        file.write(text)
        file.close()
Exemple #12
0
class ClientWindow(QDialog):

    def __init__(self):
        super(ClientWindow, self).__init__()

        self.resize(823,511)
        self.setWindowTitle('用户客户端')
        self.friendList = QListWidget()
        self.friendList.doubleClicked.connect(self.changeFriendText)
        self.friendList.clicked.connect(self.changeFriendText)
        self.portLine = QLineEdit()
        self.portLine.setText('12345')
        self.connectBtn = QPushButton('连接')
        self.connectBtn.clicked.connect(self.setupFun)
        self.messageText = QTextEdit()
        self.messageLine = QLineEdit()
        self.sendBtn = QPushButton('发送')
        self.sendBtn.clicked.connect(self.sendFun)

        self.text = ''
        self.userText = {}

        self.initUI()
        self.palette = QPalette()
        self.palette.setBrush(QPalette.Background, QBrush(QPixmap('./image/background.jpg')))
        self.setPalette(self.palette)
        self.client = Client()
        self.client.trigger.connect(self.updateTextFun)
        self.ininData()

    def changeFriendText(self):
        currentItem = self.friendList.currentItem().text()
        self.text = self.userText[currentItem]
        self.messageText.setText(self.text)

    def ininData(self):
        self.friendList.addItem('broadcast')
        self.userText['broadcast'] = ''
        self.friendList.setCurrentItem(self.friendList.item(0))

    def initUI(self):

        mainLayout = QVBoxLayout()
        mainWidget = QWidget()

        widget1 = QWidget()
        layout1 = QHBoxLayout()
        layout1.addWidget(self.portLine)
        layout1.addWidget(self.connectBtn)
        widget1.setLayout(layout1)
        mainLayout.addWidget(widget1)

        widget2 = QWidget()
        layout2 = QHBoxLayout()
        layout2.addWidget(self.messageText)
        layout2.addWidget(self.friendList)
        layout2.setStretch(0,2)
        layout2.setStretch(0,1)
        widget2.setLayout(layout2)
        mainLayout.addWidget(widget2)

        # mainLayout.addStretch(1)
        widget3 = QWidget()
        layout3 = QHBoxLayout()
        layout3.addWidget(self.messageLine)
        layout3.addWidget(self.sendBtn)
        widget3.setLayout(layout3)
        mainLayout.addWidget(widget3)

        self.setLayout(mainLayout)

    def setupFun(self):
        port = int(self.portLine.text())
        self.client.setupFun(port)
        self.client.start()

    def sendFun(self):
        addr = self.friendList.currentItem().text()
        message = self.messageLine.text()
        if message != 'add' and message != 'del':
            self.userText[addr] += '我:' + message + '\n'
        self.changeFriendText()
        if addr != 'broadcast':
            addr = ('localhost',int(addr))
        self.client.sendFun(message,addr)
        self.messageLine.setText('')


    def updateTextFun(self,data):

        currentItem = self.friendList.currentItem().text()
        data = json.loads(data)
        if 'cmd' in data.keys():
            if data['cmd'] == 'add':
                fromUser = str(data['from'])
                addr = ('127.0.0.1',int(fromUser))
                item = self.friendList.findItems(fromUser,Qt.MatchExactly)
                if fromUser not in self.userText.keys():
                    self.userText[fromUser] = ''
                if len(item) == 0:
                    self.friendList.addItem(fromUser)
                    self.client.sendFun('add',addr)  # 已添加
            elif data['cmd'] == 'del':
                fromUser = str(data['from'])
                rows = self.friendList.count()
                for row in range(rows):
                    if fromUser == self.friendList.item(row).text():
                        self.friendList.takeItem(row)
        else:
            message = data['message']
            fromUser = str(data['from'])
            if fromUser != 'broadcast':
                addr = ('127.0.0.1', int(fromUser))
                item = self.friendList.findItems(fromUser, Qt.MatchExactly)
                if fromUser not in self.userText.keys():
                    self.userText[fromUser] = ''
                if len(item) == 0:
                    self.friendList.addItem(fromUser)
                    self.client.sendFun('add', addr)  # 已添加
            if message != 'add' and message != 'del':
                self.userText[fromUser] += fromUser + ':' + message + '\n'
                if fromUser == currentItem:
                    self.text = self.userText[fromUser]
                    self.messageText.setText(self.text)


    def closeEvent(self, event:PySide2.QtGui.QCloseEvent):
        self.client.closeFun()
Exemple #13
0
class WetSand(QWidget):
    def __init__(self):
        super().__init__()

        # Init list
        self.list = QListWidget()
        self.list.addItem(WetListItem("You don't form in the wet sand"))
        self.list.addItem(WetListItem("You don't form at all"))

        # Init buttons
        self.btns = [
            WetButton('johs'),
            WetButton('jon'),
            WetButton('feel'),
            WetButton('chat'),
            WetButton('tony')
        ]

        # Freeze and unfreeze buttons
        self.freeze_btn = QPushButton('Freeze me')
        self.unfreeze_btn = QPushButton('Unfreeze me')

        # Layout stuff
        self.btn_lyt = QVBoxLayout()
        for btn in self.btns:
            self.btn_lyt.addWidget(btn)

        self.top_lyt = QHBoxLayout()
        self.top_lyt.addWidget(self.list)
        self.top_lyt.addLayout(self.btn_lyt)

        self.bottom_lyt = QHBoxLayout()
        self.bottom_lyt.addWidget(self.freeze_btn)
        self.bottom_lyt.addWidget(self.unfreeze_btn)

        self.main_lyt = QVBoxLayout()
        self.main_lyt.addLayout(self.top_lyt)
        self.main_lyt.addLayout(self.bottom_lyt)

        # Signals and slots
        # Use functools.partial to send arguments
        self.freeze_btn.clicked.connect(partial(self.freeze, True))
        self.unfreeze_btn.clicked.connect(partial(self.freeze, False))

        # Don't forget me
        self.setLayout(self.main_lyt)
        self.show()

    @Slot()
    def freeze(self, yes=True):
        # Freeze buttons
        print(yes)
        btns = (self.btn_lyt.itemAt(i).widget()
                for i in range(self.btn_lyt.count()))
        for btn in btns:
            btn.set_clickable(not yes)

        # Freeze list items
        list_items = [self.list.item(i) for i in range(self.list.count())]
        for list_item in list_items:
            list_item.set_selectable(not yes)
class Widgets(QWidget):
    def __init__(self, gui, app):
        super(Widgets, self).__init__()
        self.gui = gui
        self.app = app
        self.setWindowTitle("Dark Souls Boss Tracker")
        self.setGeometry(800, 400, 250, 200)
        self.new_run_label = QLabel("Run name:")
        self.new_run_field = QLineEdit(self)
        self.new_run_button = QPushButton("Start New Run", self)
        self.new_run_button.clicked.connect(self.new_run)
        self.previous_label = QLabel("Previous runs:")
        self.previous_runs = QListWidget(self)
        self.previous_runs.itemClicked.connect(self.select_run)
        self.selected = None
        self.resume_button = QPushButton("Resume Run", self)
        self.resume_button.clicked.connect(self.resume)
        self.delete_button = QPushButton("Delete Run", self)
        self.delete_button.clicked.connect(self.delete_run)

        self.layout = QGridLayout()
        self.layout.addWidget(self.new_run_label, 0, 0)
        self.layout.addWidget(self.new_run_field, 1, 0)
        self.layout.addWidget(self.new_run_button, 1, 1)
        self.layout.addWidget(self.previous_label, 2, 0)
        self.layout.addWidget(self.previous_runs, 3, 0)
        self.layout.addWidget(self.resume_button, 4, 0)
        self.layout.addWidget(self.delete_button, 4, 1)
        self.get_tables()

        self.setLayout(self.layout)

    def get_tables(self):
        self.previous_runs.clear()
        my_list = boss_tracker.get_tables()
        if my_list is not None:
            for i in my_list:
                self.previous_runs.addItem(i[0])
        # print(my_list)

    def select_run(self, item):
        self.selected = item.text()

    def new_run(self):
        new_run_pattern = re.compile(r"[^a-zA-Z0-9_-]")
        error = new_run_pattern.search(self.new_run_field.text())
        for i in range(self.previous_runs.count()):
            if self.new_run_field.text() == self.previous_runs.item(i).text():
                error = True
        if not error and len(self.new_run_field.text()) > 3:
            Order().show()
            boss_tracker.start_new_run(self.new_run_field.text(), self.app)
            self.previous_runs.addItem(self.new_run_field.text())
            self.gui.close()
        else:
            ErrorWindow(
                "Username too short has special characters or already in use.")

    def resume(self):
        if self.selected is not None:
            boss_tracker.resume_run(self.selected)
            self.gui.close()

    def delete_run(self):
        print(self.selected)
        if self.selected is not None:
            boss_tracker.delete_table(self.selected)
            self.get_tables()
Exemple #15
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()
class ReportListComponent(QGroupBox):
    currentAnalysisChanged = Signal(object)

    def __init__(self):
        super().__init__()

        self.setTitle("Rapports disponibles")

        main_layout = QVBoxLayout(self)
        self._list = QListWidget()
        self._list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._list.customContextMenuRequested.connect(self._showItemMenu)
        self._list.currentRowChanged.connect(self._currentAnalysisChanged)
        self._list.itemDoubleClicked.connect(lambda item: self._renameItem())

        self._analysis = None

        main_layout.addWidget(self._list)

    def reset(self, analysis: Analysis):
        self._current_analysis_file = None
        self._analysis = analysis

        self._list.clear()
        for analysis in HistoryManager.analysisList():
            item = QListWidgetItem("%s (%s)" % (analysis["name"], analysis["date"]))
            item.setData(Qt.UserRole, analysis["file"])
            item.setData(Qt.UserRole + 1, analysis["name"])
            self._list.addItem(item)
        
        self._list.setCurrentRow(0)

    @Slot(int)
    def _currentAnalysisChanged(self, row: int):
        if row < 0:
            return
        
        new_analysis_file = self._list.item(row).data(Qt.UserRole)

        if self._current_analysis_file == new_analysis_file:
            return

        if self._current_analysis_file is None:
            self._current_analysis_file = new_analysis_file
            return

        self._current_analysis_file = new_analysis_file
        self._analysis = HistoryManager.loadAnalysis(new_analysis_file)
        self.currentAnalysisChanged.emit(self._analysis)

    @Slot(QPoint)
    def _showItemMenu(self, pos: QPoint):
        globalPos = self._list.mapToGlobal(pos)

        actions_menu = QMenu()
        actions_menu.addAction("Renommer", self._renameItem)
        actions_menu.addAction("Supprimer",  self._eraseItem)

        actions_menu.exec_(globalPos)

    @Slot()
    def _renameItem(self):
        item = self._list.currentItem()
        
        input_dialog = QInputDialog(self.parentWidget(), Qt.WindowSystemMenuHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
        font = input_dialog.font()
        font.setPixelSize(16)
        input_dialog.setFont(font)
        input_dialog.setMinimumWidth(300)
        input_dialog.setInputMode(QInputDialog.TextInput)
        input_dialog.setWindowTitle("Renommer l'analyse")
        input_dialog.setLabelText("Nouveau nom pour '%s' :" % item.data(Qt.UserRole + 1))
        input_dialog.setTextValue(item.data(Qt.UserRole + 1))
        input_dialog.setOkButtonText("OK")
        input_dialog.setCancelButtonText("Annuler")

        if not input_dialog.exec_():
            return
        
        new_name = input_dialog.textValue()

        if self._analysis is None:
            return

        if new_name == self._analysis.parameters().name():
            return
        
        regexp = QRegExp("^[a-zA-Z0-9_-#éèêëàîï ]{5,30}$")
        
        if not regexp.exactMatch(new_name):
            QMessageBox.warning(self, "Nouveau nom invalide", "Caractères autorisés : alphanumérique, espace, #, - et _ avec une longueur maximale de 30 caractères")
            return


        self._analysis.parameters().setName(new_name)
        HistoryManager.renameAnalysis(item.data(Qt.UserRole), self._analysis)
        
        current_row = self._list.currentRow()
        self.reset(self._analysis)
        self._list.setCurrentRow(current_row)
        self.currentAnalysisChanged.emit(self._analysis)

    @Slot()
    def _eraseItem(self):
        item = self._list.currentItem()

        message_box = QMessageBox()
        message_box.setIcon(QMessageBox.Warning)
        message_box.setWindowTitle("Supprimer une analyse ?")
        message_box.setText("Voulez vous vraiment supprimer l'analyse '%s' de façon définitive ?" % item.data(Qt.UserRole + 1))
        message_box.setInformativeText("Assurez vous d'avoir exportez toutes les données dont vous avez besoin.")
        message_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)

        ret = message_box.exec_()
        if ret == QMessageBox.Yes:
            HistoryManager.deleteAnalysis(item.data(Qt.UserRole))
            self._list.takeItem(self._list.currentRow())

        if self._list.currentRow() == -1:
            self.currentAnalysisChanged.emit(None)
Exemple #17
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)
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)
Exemple #19
0
from PySide2 import QtCore
from PySide2.QtWidgets import QApplication, QListWidget, QComboBox

if __name__ == '__main__':
    """
    Two views using each one a instance of our data
    When the data is change in QListWidget(), the data in QComboBox will not be changed
    """

    app = QApplication(sys.argv)

    # Let's make the QListWidget show this data
    data = ["ONE", "TWO", "THREE", "FOUR", "FIVE"]

    list_widget = QListWidget()
    list_widget.show()
    list_widget.addItems(data)

    # Let's make elements on QListWidget editable
    for index in range(list_widget.count()):
        item = list_widget.item(index)
        item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)

    # A comboBox showing the same data
    comboBox = QComboBox()
    comboBox.show()
    comboBox.addItems(data)

    sys.exit(app.exec_())
Exemple #20
0
def get_attribute_widget(index: int,
                         list_widget: QListWidget) -> FieldAttrFrame:
    item = list_widget.item(index)
    return list_widget.itemWidget(item)
Exemple #21
0
class PersonaUI(QWidget):
    """
    Widget for Persona creation view.

    :param MainFrame mainframe: application mainframe
    :param QWidget op: parent widget
    """
    def __init__(self, mainframe, op):
        QWidget.__init__(self)
        self.mainframe = mainframe
        self.op = op

        self.grid = QGridLayout()
        self.setLayout(self.grid)

        self.listP = None
        self.listLS = None
        self.listEL1 = None
        self.listEL2 = None

        self.nameT = None
        self.levelT = None
        self.textT = None
        self.strT = None
        self.magT = None
        self.endT = None
        self.agiT = None
        self.luckT = None

        self.createFrame = None
        self.buttonFrame = None
        self.bfgrid = None
        # Actual create frame variables.
        self.cfgrid = None
        self.lsdic = None
        self.slashO = None
        self.strikeO = None
        self.pierceO = None
        self.fireO = None
        self.iceO = None
        self.windO = None
        self.elecO = None
        self.darkO = None
        self.lightO = None
        self.arcO = None
        self.iSpellOs = None
        self.lsSpellO = None
        self.lslevel = None


        self.initUI(True)

    def initUI(self, infoDump):
        """
        Initializes the basic UI showing the list of Personas.
        Does a lot of stuff.

        :param dict infoDump: not sure lol
        """
        self.mainframe.setWindowTitle("Persona Creator")

        if not infoDump:
            self.createFrameDraw()

        self.initButtonFrame(infoDump)

        self.listP = QListWidget(self)
        self.grid.addWidget(self.listP, 0, 3, 2, 1)
        temp = json_reader.readPerNames()
        self.listP.addItems(temp)

    def initButtonFrame(self, infoDump):
        """
        Initializes the buttonframes that are present in all Persona creator views.

        :param dict infoDump: not sure lol
        """
        self.buttonFrame = QWidget(self)
        self.bfgrid = QGridLayout()
        self.buttonFrame.setLayout(self.bfgrid)

        self.grid.addWidget(self.buttonFrame, 3, 0, 1, 4)


        new = QPushButton(self.buttonFrame, text="New")
        new.clicked.connect(self.new)
        self.bfgrid.addWidget(new, 4, 0)

        back = QPushButton(self.buttonFrame, text="Back")
        back.clicked.connect(self.back)
        self.bfgrid.addWidget(back, 4, 4)

        remove = QPushButton(self.buttonFrame, text="Remove")
        remove.clicked.connect(self.remove)
        self.bfgrid.addWidget(remove, 4, 3)

        edit = QPushButton(self.buttonFrame, text="Edit")
        edit.clicked.connect(self.edit)
        self.bfgrid.addWidget(edit, 4, 2)

        if not infoDump:
            save = QPushButton(self.buttonFrame, text="Save")
            save.clicked.connect(self.save)
            self.bfgrid.addWidget(save, 4, 1)


    def createFrameDraw(self):
        """
        Initializes the GUI of the actual creation frame view.
        Does a LOT of stuff.
        """
        self.createFrame = QWidget(self)
        self.cfgrid = QGridLayout()
        self.createFrame.setLayout(self.cfgrid)
        self.grid.addWidget(self.createFrame, 0, 0, 2, 2)

        self.lsdic = {}

        nameL = QLabel(self.createFrame, text="Name:")
        self.cfgrid.addWidget(nameL, 0, 0)
        self.nameT = QLineEdit(self.createFrame)
        self.nameT.setFixedSize(100, 20)
        self.cfgrid.addWidget(self.nameT, 0, 1)

        strL = QLabel(self.createFrame, text="Str")
        self.cfgrid.addWidget(strL, 0, 2)
        self.strT = QLineEdit(self.createFrame)
        self.strT.setFixedSize(20, 20)
        self.cfgrid.addWidget(self.strT, 0, 3)
        magL = QLabel(self.createFrame, text="Mag")
        self.cfgrid.addWidget(magL, 1, 2)
        self.magT = QLineEdit(self.createFrame)
        self.magT.setFixedSize(20, 20)
        self.cfgrid.addWidget(self.magT, 1, 3)
        endL = QLabel(self.createFrame, text="End")
        self.cfgrid.addWidget(endL, 2, 2)
        self.endT = QLineEdit(self.createFrame)
        self.endT.setFixedSize(20, 20)
        self.cfgrid.addWidget(self.endT, 2, 3)
        agiL = QLabel(self.createFrame, text="Agi")
        self.cfgrid.addWidget(agiL, 3, 2)
        self.agiT = QLineEdit(self.createFrame)
        self.agiT.setFixedSize(20, 20)
        self.cfgrid.addWidget(self.agiT, 3, 3)
        luckL = QLabel(self.createFrame, text="Luck")
        self.cfgrid.addWidget(luckL, 4, 2)
        self.luckT = QLineEdit(self.createFrame)
        self.luckT.setFixedSize(20, 20)
        self.cfgrid.addWidget(self.luckT, 4, 3)

        resList = json_reader.data_list("resistances")
        resL = QLabel(self.createFrame, text="Resistance:")
        self.cfgrid.addWidget(resL, 0, 5)
        slashL = QLabel(self.createFrame, text="Slash")
        self.cfgrid.addWidget(slashL, 1, 5)
        self.slashO = QComboBox(self.createFrame)
        self.slashO.addItems(resList)
        self.slashO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.slashO, 1, 6)
        strikeL = QLabel(self.createFrame, text="Strike")
        self.cfgrid.addWidget(strikeL, 2, 5)
        self.strikeO = QComboBox(self.createFrame)
        self.strikeO.addItems(resList)
        self.strikeO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.strikeO, 2, 6)
        pierceL = QLabel(self.createFrame, text="Pierce")
        self.cfgrid.addWidget(pierceL, 3, 5)
        self.pierceO = QComboBox(self.createFrame)
        self.pierceO.addItems(resList)
        self.pierceO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.pierceO, 3, 6)
        fireL = QLabel(self.createFrame, text="Fire")
        self.cfgrid.addWidget(fireL, 4, 5)
        self.fireO = QComboBox(self.createFrame)
        self.fireO.addItems(resList)
        self.fireO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.fireO, 4, 6)
        iceL = QLabel(self.createFrame, text="Ice")
        self.cfgrid.addWidget(iceL, 5, 5)
        self.iceO = QComboBox(self.createFrame)
        self.iceO.addItems(resList)
        self.iceO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.iceO, 5, 6)
        elecL = QLabel(self.createFrame, text="Elec")
        self.cfgrid.addWidget(elecL, 6, 5)
        self.elecO = QComboBox(self.createFrame)
        self.elecO.addItems(resList)
        self.elecO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.elecO, 6, 6)
        windL = QLabel(self.createFrame, text="Wind")
        self.cfgrid.addWidget(windL, 7, 5)
        self.windO = QComboBox(self.createFrame)
        self.windO.addItems(resList)
        self.windO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.windO, 7, 6)
        lightL = QLabel(self.createFrame, text="Light")
        self.cfgrid.addWidget(lightL, 8, 5)
        self.lightO = QComboBox(self.createFrame)
        self.lightO.addItems(resList)
        self.lightO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.lightO, 8, 6)
        darkL = QLabel(self.createFrame, text="Dark")
        self.cfgrid.addWidget(darkL, 9, 5)
        self.darkO = QComboBox(self.createFrame)
        self.darkO.addItems(resList)
        self.darkO.setCurrentIndex(1)
        self.cfgrid.addWidget(self.darkO, 9, 6)

        spellList = json_reader.data_list("spells")
        self.listLS = QListWidget(self.createFrame)
        self.listLS.setFixedSize(200, 300)
        self.cfgrid.addWidget(self.listLS, 3, 7, 8, 2)

        newLS = QPushButton(self.createFrame, text="+")
        newLS.clicked.connect(self.addLS)
        self.cfgrid.addWidget(newLS, 2, 7)
        delLS = QPushButton(self.createFrame, text="DEL")
        delLS.clicked.connect(self.delLS)
        self.cfgrid.addWidget(delLS, 2, 8)

        lsl = QLabel(self.createFrame, text="Learned Spells:")
        self.cfgrid.addWidget(lsl, 0, 7, 1, 2)

        arcanaL = QLabel(self.createFrame, text="Arcana:")
        self.cfgrid.addWidget(arcanaL, 1, 0)
        arc_list = json_reader.data_list("arcanas")
        self.arcO = QComboBox(self.createFrame)
        self.arcO.addItems(arc_list)
        self.arcO.setCurrentIndex(0)
        self.cfgrid.addWidget(self.arcO, 1, 1)

        levelL = QLabel(self.createFrame, text="Level:")
        self.cfgrid.addWidget(levelL, 2, 0)
        self.levelT = QLineEdit(self.createFrame)
        self.levelT.setFixedSize(20, 20)
        self.cfgrid.addWidget(self.levelT, 2, 1)

        heritageL = QLabel(self.createFrame, text="Inherits:")
        self.cfgrid.addWidget(heritageL, 3, 0, 1, 2)

        elements = json_reader.data_list("elements")
        elements.append("Support")
        self.listEL1 = QComboBox(self.createFrame)
        self.listEL1.addItems(elements)
        self.cfgrid.addWidget(self.listEL1, 4, 0)
        self.listEL2 = QComboBox(self.createFrame)
        self.listEL2.addItems(elements)
        self.cfgrid.addWidget(self.listEL2, 4, 1)

        iSpellL = QLabel(self.createFrame, text="Initial Spells:")
        self.cfgrid.addWidget(iSpellL, 5, 0, 1, 2)
        self.iSpellOs = []
        for i in range(6, 9):
            temp = QComboBox(self.createFrame)
            temp.addItems(spellList)
            temp2 = QComboBox(self.createFrame)
            temp2.addItems(spellList)
            self.cfgrid.addWidget(temp, i, 0, 1, 2)
            self.cfgrid.addWidget(temp2, i, 2, 1, 2)
            self.iSpellOs.extend([temp, temp2])

        textL = QLabel(self.createFrame, text="Info:")
        self.cfgrid.addWidget(textL, 10, 0)
        self.textT = QTextEdit(self.createFrame)
        self.textT.setFixedSize(300, 100)
        self.cfgrid.addWidget(self.textT, 10, 1, 1, 5)

        self.lslevel = QLineEdit(self.createFrame)
        self.lslevel.setFixedSize(40, 20)
        self.lsSpellO = QComboBox(self.createFrame)
        self.lsSpellO.addItems(spellList)

        self.cfgrid.addWidget(self.lsSpellO, 1, 7)
        self.cfgrid.addWidget(self.lslevel, 1, 8)

    def addLS(self):
        """
        Add a learned spell to the list, based on what was entered.
        """
        print("Adding learned spell")
        chosenSpell = self.lsSpellO.currentText()
        if (int)(self.lslevel.text()) <= (int)(self.levelT.text()):
            popup("You cannot add a spell at an earlier level than the Persona's base level", "Critical")
            return
        if chosenSpell != "":
            print("Ok")
            self.lsdic[chosenSpell] = self.lslevel.text()
            self.listLS.addItem(chosenSpell + " at level " + self.lslevel.text())
            self.lslevel.setText("")
            self.lsSpellO.setCurrentIndex(0)
            return
        popup("You must choose a spell", "Critical")

    def delLS(self):
        """
        Remove the selected learned spell from the list
        """
        print("Deleting learned spell")
        key = ""
        i = 0
        while len(self.listLS.currentItem().text()) > i:
            if self.listLS.currentItem().text()[i] == " " and \
               self.listLS.currentItem().text()[i+1] == "a" and \
               self.listLS.currentItem().text()[i+2] == "t":  # TODO EWWWWWW
                break
            key += self.listLS.currentItem().text()[i]
            i = i + 1
        print(key)
        print(self.lsdic.pop(key))
        self.listLS.takeItem(self.listLS.currentRow())


    def loadPer(self, name):
        """
        Load a certain Persona from file.

        :param str name: name of Persona to load
        """
        data = json_reader.readOne(name, 'pers')
        self.nameT.setText(data["name"])
        self.textT.setText(data["desc"])
        self.strT.setText(data["stats"][0])
        self.magT.setText(data["stats"][1])
        self.endT.setText(data["stats"][2])
        self.agiT.setText(data["stats"][3])
        self.luckT.setText(data["stats"][4])
        self.levelT.setText(data["level"])

        self.arcO.setCurrentIndex(
            [self.arcO.itemText(i) for i in range(self.arcO.count())].index(data["arcana"])
        )

        self.listEL1.setCurrentIndex(
            [self.listEL1.itemText(i) for i in range(self.listEL1.count())].index(data["heritage"][0])
        )
        self.listEL2.setCurrentIndex(
            [self.listEL2.itemText(i) for i in range(self.listEL2.count())].index(data["heritage"][1])
        )

        self.slashO.setCurrentIndex(
            [self.slashO.itemText(i) for i in range(self.slashO.count())].index(data["resistance"][0])
        )
        self.strikeO.setCurrentIndex(
            [self.strikeO.itemText(i) for i in range(self.strikeO.count())].index(data["resistance"][1])
        )
        self.pierceO.setCurrentIndex(
            [self.pierceO.itemText(i) for i in range(self.pierceO.count())].index(data["resistance"][2])
        )
        self.fireO.setCurrentIndex(
            [self.fireO.itemText(i) for i in range(self.fireO.count())].index(data["resistance"][3])
        )
        self.iceO.setCurrentIndex(
            [self.iceO.itemText(i) for i in range(self.iceO.count())].index(data["resistance"][4])
        )
        self.elecO.setCurrentIndex(
            [self.elecO.itemText(i) for i in range(self.elecO.count())].index(data["resistance"][5])
        )
        self.windO.setCurrentIndex(
            [self.windO.itemText(i) for i in range(self.windO.count())].index(data["resistance"][6])
        )
        self.lightO.setCurrentIndex(
            [self.lightO.itemText(i) for i in range(self.lightO.count())].index(data["resistance"][7])
        )
        self.darkO.setCurrentIndex(
            [self.darkO.itemText(i) for i in range(self.darkO.count())].index(data["resistance"][8])
        )

        i = 0
        for combobox in self.iSpellOs:
            combobox.setCurrentIndex(
                [combobox.itemText(j) for j in range(combobox.count()-1)].index(data["spellDeck"][i])
            )
            i += 1

        self.lsdic = data["spellLearn"]
        self.listLS.clear()
        for spell, level in self.lsdic.items():
            self.listLS.addItem(spell + " at level " + level)

        print("Loaded " + data["name"])

    def edit(self):
        """
        Switch to edit view, also loads the selected Persona.
        """
        try:
            if self.listP.currentItem().text() != "":
                if self.createFrame and not popup("Override any unsaved changes?", "Warning"):
                    return
                self.loadPer(self.listP.currentItem().text())
        except AttributeError:  # To initialize createFrame UI before load
            if self.listP.currentItem().text() != "":
                temp = self.listP.currentItem().text()
                self.buttonFrame.close()
                self.initUI(False)
                self.loadPer(temp)
            else:
                return
        self.createFrame.show()
        self.mainframe.center()
        print("Changed to edit frame")

    def save(self):
        """
        Validate all info and save to file on disk.
        """
        if os.path.exists(json_reader.buildPath("data/pers/"+self.nameT.text()+".json")):
            if not popup("Override existing Persona "+self.nameT.text()+"?", "Question"):
                return
        print("Saving")
        spellDeck = []
        for combobox in self.iSpellOs:
            spellDeck.append(combobox.currentText())
        stats = [self.strT.text(), self.magT.text(), self.endT.text(), self.agiT.text(), self.luckT.text()]
        res = [self.slashO.currentText(), self.strikeO.currentText(), self.pierceO.currentText(),
               self.fireO.currentText(), self.iceO.currentText(), self.elecO.currentText(),
               self.windO.currentText(), self.lightO.currentText(), self.darkO.currentText()]
        try:
            (int)(self.levelT.text())
            (int)(self.strT.text())
            (int)(self.magT.text())
            (int)(self.endT.text())
            (int)(self.agiT.text())
            (int)(self.luckT.text())
        except ValueError:
            popup("There is a number entry that isn't valid.\nEntries requiring numbers are:\nLEVEL\nSTR"
                  "\nMAG\nEND\nAGI\nLUCK", "Critical")
            print("Not Saved")
            return
        if not (self.nameT.text() and not self.nameT.text().isspace()):
            popup("No name entered for your Persona. Name is a required field.", "Critical")
            print("No Name, not saved")
            return
        toWrite = Persona(
            self.nameT.text(),
            self.arcO.currentText(),
            self.levelT.text(),
            self.textT.toPlainText(),
            spellDeck,
            self.lsdic,
            stats,
            res,
            [self.listEL1.currentText(), self.listEL2.currentText()]
        )
        json_reader.writeOne(toWrite, 'pers')
        temp = self.nameT.text()
        if (temp not in [self.listP.item(i).text() for i in range(self.listP.count())]):
            self.listP.addItem(temp)
        self.loadPer(temp)
        print("Saved Persona")

    def remove(self):
        """
        Remove a created Persona from the list and delete the file on disk.
        """
        if self.listP.currentItem().text() == "":
            return
        if not popup(
                "Are you certain you want to completely remove this Persona?\n(Cannot be undone)", "Warning"
            ):
            return
        print("Removing Persona " + self.listP.currentItem().text())
        json_reader.deletePer(self.listP.currentItem().text())
        self.listP.takeItem(
            [self.listP.item(i).text() for i in range(self.listP.count())].index(
                self.listP.currentItem().text())
        )

    def new(self):
        """
        Open an empty Persona edit view.
        """
        if self.createFrame and not popup("Override any unsaved changes?", "Warning"):
            return
        if self.createFrame:
            self.createFrame.close()
        self.buttonFrame.close()
        self.initUI(False)
        self.createFrame.show()
        self.mainframe.center()
        print("Created")

    def back(self):
        """
        Return to the parent widget.
        """
        print("Returned to main screen")
        self.mainframe.changeState(self.op)
class MainFrame(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Define buttons
        # Button to calculate lunar dates
        self.calculate_lunar = QPushButton('음력날짜 계산', self)
        self.calculate_lunar.clicked.connect(self.calculate_lunar_date)
        self.calculate_lunar.setGeometry(20, 260, 130, 35)
        self.calculate_lunar.setStatusTip('음력 날짜를 계산합니다.')
        self.calculate_lunar.setShortcut('Return')

        # Button to save ICS file to local directory
        self.ICS_save_button = QPushButton('ICS 파일 저장', self)
        self.ICS_save_button.clicked.connect(self.create_ics_file)
        self.ICS_save_button.setGeometry(175, 260, 130, 35)
        self.ICS_save_button.setStatusTip('ICS 파일을 컴퓨터에 저장합니다.')

        # Define labels
        # Define label for lunar date to convert
        lunar_date_text = QLabel(self)
        lunar_date_text.setText('계산할 음력 날짜')
        lunar_date_text.setGeometry(25, 15, 240, 25)

        # Define label for name of event
        event_name_text = QLabel(self)
        event_name_text.setText('이벤트 이름 입력')
        event_name_text.setGeometry(25, 50, 240, 25)

        # Define label for repetition
        event_name_text = QLabel(self)
        event_name_text.setText('몇년치나 할까요?')
        event_name_text.setGeometry(25, 85, 240, 25)

        # Define ListWidget to display results
        self.result_console = QListWidget(self)
        self.result_console.setGeometry(25, 118, 275, 133)
        self.result_console.setStatusTip('올해부터 매년 양력날짜가 출력됩니다.')

        # Define user input areas
        # Define lunar date to convert to solar date
        self.user_date_input = QLineEdit(self)
        self.user_date_input.setGeometry(180, 15, 120, 27)
        self.user_date_input.setAlignment(Qt.AlignCenter)
        self.user_date_input.setPlaceholderText('YYYYMMDD')
        self.user_date_input.setStatusTip('날짜를 YYYYMMDD로 입력하세요.')

        # Define name of event to use in ICS file
        self.user_event_name = QLineEdit(self)
        self.user_event_name.setGeometry(180, 50, 120, 27)
        self.user_event_name.setAlignment(Qt.AlignCenter)
        self.user_event_name.setPlaceholderText('이벤트 이름')
        self.user_event_name.setStatusTip('이벤트 이름을 입력하세요.')

        # Define number of years to convert
        self.user_repetition = QLineEdit(self)
        self.user_repetition.setGeometry(180, 84, 120, 27)
        self.user_repetition.setAlignment(Qt.AlignCenter)
        self.user_repetition.setText('10')
        self.user_repetition.setStatusTip('생성할 햇수를 입력하세요.')

        # Define size of main window
        self.setGeometry(200, 320, 325, 330)
        self.setWindowTitle('날짜')
        self.statusBar()
        self.show()

    # Define functions
    # Function to parse lunar date from openAPI website using user input
    def calculate_lunar_date(self):
        if len(self.user_date_input.text()) != 8:
            reply = QMessageBox.question(self, 'Error',
                                         "YYYYMMDD로 정확한 날짜를 입력해 주십시오.",
                                         QMessageBox.Close)
            return

        url = 'http://apis.data.go.kr/B090041/openapi/service/LrsrCldInfoService/getSolCalInfo'
        personal_key = 'UrEdHGIOCJr600RsRQ%2BnoL2wma3HT9JXmYn0uhHwmxImsnE2GHKYfn1RUfiEK9RIHXPJ3FBRnONxXMjplU3%2F7g%3D%3D'
        lunar_input = self.user_date_input.text()
        lunar_month = lunar_input[4:6]
        lunar_day = lunar_input[6:]
        repeat = int(self.user_repetition.text()) + 1

        for i in range(0, repeat):
            lunar_year = int(lunar_input[:4]) + int(i)
            # Limit search at lunar year 2050.
            if lunar_year > 2050:
                break

            query_params = '?lunYear={}&lunMonth={}&lunDay={}&ServiceKey={}'.format(
                lunar_year, lunar_month, lunar_day, personal_key)
            session = XMLSession()
            r = session.get(url + query_params)
            solar_day = r.xml.xpath('//solDay', first=True).text
            solar_month = r.xml.xpath('//solMonth', first=True).text
            solar_year = r.xml.xpath('//solYear', first=True).text
            solar_week = r.xml.xpath('//solWeek', first=True).text
            solar_date_text = '   {}년 {}월 {}일 {}요일 '.format(
                solar_year, solar_month, solar_day, solar_week)

            QListWidgetItem(solar_date_text, self.result_console)

    def create_ics_file(self):
        event_name = self.user_event_name.text()
        ics_content = 'BEGIN:VCALENDAR\nVERSION:2.0\nCALSCALE:GREGORIAN\nBEGIN:VTIMEZONE\nTZID:Asia/Tokyo\n' \
                      'TZURL:http://tzurl.org/zoneinfo-outlook/Asia/Tokyo\nX-LIC-LOCATION:Asia/Tokyo\n' \
                      'BEGIN:STANDARD\nTZOFFSETFROM:+0900\nTZOFFSETTO:+0900\nTZNAME:JST\n' \
                      'DTSTART:19700101T000000\nEND:STANDARD\nEND:VTIMEZONE\n'

        if len(self.user_event_name.text()) == 0:
            reply = QMessageBox.question(self, 'Error', "이벤트 이름을 입력해 주십시오.",
                                         QMessageBox.Close)
            return
        elif self.result_console.count() == 0:
            reply = QMessageBox.question(self, 'Error', "날짜 계산을 먼저 해주십시오.",
                                         QMessageBox.Close)
            return

        # Iterate through QListWidget items: https://stackoverflow.com/a/34479509
        converted_dates = [
            str(self.result_console.item(i).text())
            for i in range(self.result_console.count())
        ]
        for i in converted_dates:
            # Extract digits from string: https://stackoverflow.com/a/26825833
            date_string = (''.join(filter(str.isdigit, i)))
            event_string = 'BEGIN:VEVENT\nDTSTAMP:20180802T115053z\nDTSTART;TZID="Asia/Tokyo":{0}T120000' \
                           '\nDTEND;TZID="Asia/Tokyo":{0}T120000\nSUMMARY:{1}\nBEGIN:VALARM\n' \
                           'TRIGGER:-PT14H\nREPEAT:1\nACTION:DISPLAY\nDESCRIPTION:Reminder\nEND:VALARM\nEND:VEVENT\n'
            ics_content += event_string.format(date_string, event_name)

        ics_content += 'END:VCALENDAR'

        # This program cannot read existing .ics files, so if user creates a new ics event with existing file name,
        # the program would crash.
        new_ics = open(event_name.replace(' ', '') + '.ics', 'w')
        new_ics.write(ics_content)
        new_ics.close()

        success = QMessageBox.question(self, 'Success', "ICS 파일 생성 완료!",
                                       QMessageBox.Close)
Exemple #23
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."
        )
 def _remove_addr(self, qlist: QListWidget, addr):
     for i in range(qlist.count()):
         qitem = qlist.item(i)
         if int(qitem.text(), 16) == addr:
             qlist.takeItem(i)
             return
Exemple #25
0
class QtEpsInfo(QtWidgets.QWidget, Ui_EpsInfo):
    def __init__(self, owner):
        super(self.__class__, self).__init__()
        Ui_EpsInfo.__init__(self)
        self.setupUi(self)
        self.owner = weakref.ref(owner)

        self.epsListWidget = QListWidget()
        self.epsListWidget.setFlow(self.epsListWidget.LeftToRight)
        self.epsListWidget.setWrapping(True)
        self.epsListWidget.setFrameShape(self.epsListWidget.NoFrame)
        self.epsListWidget.setResizeMode(self.epsListWidget.Adjust)
        self.epsListWidget.itemClicked.connect(self.SelectEps)
        self.gridLayout_2.addWidget(self.epsListWidget, 1, 0)
        self.closeFlag = self.__class__.__name__
        self.bookId = ""
        self.loadingForm = QtLoading(self)
        self.setWindowTitle("章节列表")

        self.greed = QColor(18, 161, 130)
        self.blue = QColor(97, 154, 195)
        self.white = QColor(0, 0, 0, 0)

    def OpenEpsInfo(self, bookId):
        self.show()
        self.loadingForm.show()
        self.bookId = bookId
        self.epsListWidget.clear()
        if bookId not in BookMgr().books:
            self.owner().qtTask.AddHttpTask(lambda x: BookMgr().AddBookById(self.bookId, x), self.OpenBookInfoBack,
                                            cleanFlag=self.closeFlag)
        else:
            self.owner().qtTask.AddHttpTask(lambda x: BookMgr().AddBookEpsInfo(self.bookId, x), self.OpenEpsInfoBack,
                                            cleanFlag=self.closeFlag)

    def OpenBookInfoBack(self, msg):
        if msg == Status.Ok:
            self.owner().qtTask.AddHttpTask(lambda x: BookMgr().AddBookEpsInfo(self.bookId, x), self.OpenEpsInfoBack,
                                            cleanFlag=self.closeFlag)
        else:
            self.loadingForm.close()

    def OpenEpsInfoBack(self, msg):
        self.loadingForm.close()
        self.epsListWidget.clear()
        if msg == Status.Ok:
            self.UpdateEpsInfo()
        return

    def UpdateEpsInfo(self):
        self.epsListWidget.clear()
        info = BookMgr().books.get(self.bookId)
        if not info:
            return
        downloadEpsId = self.owner().downloadForm.GetDownloadEpsId(self.bookId)
        for index, epsInfo in enumerate(info.eps):
            label = QLabel(epsInfo.title)
            label.setContentsMargins(20, 10, 20, 10)
            item = QListWidgetItem(self.epsListWidget)
            item.setSizeHint(label.sizeHint())
            if index in downloadEpsId:
                item.setBackground(self.greed)
            else:
                item.setBackground(self.white)
            self.epsListWidget.setItemWidget(item, label)

    def SelectEps(self, item):
        if item.background().color() == self.greed:
            return
        elif item.background().color() == self.blue:
            item.setBackground(self.white)
        else:
            item.setBackground(self.blue)
        return

    def SelectAll(self):
        for i in range(self.epsListWidget.count()):
            item = self.epsListWidget.item(i)
            if item.background().color() == self.greed:
                continue
            item.setBackground(self.blue)
        return

    def CancleSelect(self):
        for i in range(self.epsListWidget.count()):
            item = self.epsListWidget.item(i)
            if item.background().color() == self.greed:
                continue
            item.setBackground(self.white)
        return

    def StartDownload(self):
        downloadIds = []
        for i in range(self.epsListWidget.count()):
            item = self.epsListWidget.item(i)
            if item.background().color() == self.blue:
                downloadIds.append(i)
        if not downloadIds:
            return
        self.owner().downloadForm.AddDownload(self.bookId, downloadIds)
        self.UpdateEpsInfo()
        return
Exemple #26
0
    def create_file_list(self,
                         path,
                         selected=None,
                         up=False,
                         update_list=None):
        '''Return a file list with objects populated from files/dirs in given path.

		path -- path of directory to create list elements
		selected -- name of the cwd to select in parent list
		up -- create a link to one level up
		update_list -- (QListWidget) update the given list with new path elements rather than returning a new list
		'''
        if not update_list:
            file_list = QListWidget(self)
        else:
            update_list.clear()
            file_list = update_list

        if not path and not update_list:  # if empty
            return file_list
        elif not path and update_list:
            if len(self.drives) > 0:
                for letter in self.drives:
                    try:
                        icon = QIcon(convert_to_icon(letter))
                    except Exception as e:
                        print(e)
                        traceback.print_tb(e.__traceback__)
                    update_list.addItem(QListWidgetItem(icon, letter))
            else:
                update_list.addItem(QListWidgetItem('((root))'))
            return

        # cache read contents of path to save some time and processing power?
        # TODO: could maybe also save actual QListWIdgetItems? to save on Icon creation time
        # could also copy QIcons to cached_dirs = {... 'dir_icons': [], 'file_icons': []}
        if not any(c['path'] == path for c in self.cached_dirs):
            files, dirs, dirpath = get_files(path)
            cache = {
                'path': dirpath,
                'dirs': dirs.copy(),
                'files': files.copy()
            }
            self.cached_dirs.append(cache)
            # dirs cache limit
            if len(self.cached_dirs) > 15:
                del self.cached_dirs[0]
        else:
            for c in self.cached_dirs:
                if c['path'] == path:
                    files, dirs, dirpath = c['files'].copy(), c['dirs'].copy(
                    ), c['path']

        if up:
            dirs.insert(0, os.path.abspath(os.path.join(path)))

        selected_index = -1
        if len(files) > 0:
            for i in range(len(files)):
                try:
                    icon = QIcon(
                        convert_to_icon(os.path.join(dirpath, files[i])))
                except Exception as e:
                    print(e)
                    traceback.print_tb(e.__traceback__)
                    icon = QIcon()
                files[i] = QListWidgetItem(icon, files[i])
        if len(dirs) > 0:
            for i in range(len(dirs)):
                if dirs[i] == selected:
                    selected_index = i
                try:
                    icon = QIcon(
                        convert_to_icon(
                            os.path.abspath(os.path.join(dirpath, dirs[i]))))
                except Exception as e:
                    print(e)
                    traceback.print_tb(e.__traceback__)
                    icon = QIcon()
                dirs[i] = QListWidgetItem(icon, dirs[i])

        if up:
            dirs[0].setText('..')

        if len(dirs) > 0:
            for d in dirs:
                file_list.addItem(d)
        if len(files) > 0:
            for f in files:
                file_list.addItem(f)

        if len(dirs) == 0 and len(files) == 0:
            file_list.addItem(QListWidgetItem('((empty))'))

        if selected_index >= 0:
            file_list.item(selected_index).setSelected(True)
            file_list.scrollToItem(file_list.item(selected_index))
        else:
            file_list.item(0).setSelected(True)

        if update_list:
            return
        return file_list
class QtBookInfo(QtWidgets.QWidget, Ui_BookInfo):
    def __init__(self, owner):
        super(self.__class__, self).__init__()
        Ui_BookInfo.__init__(self)
        self.setupUi(self)
        self.owner = weakref.ref(owner)
        self.loadingForm = QtLoading(self)
        self.bookId = ""
        self.url = ""
        self.path = ""
        self.bookName = ""
        self.lastEpsId = -1

        self.msgForm = QtBubbleLabel(self)
        self.picture.installEventFilter(self)
        self.title.setGeometry(QRect(328, 240, 329, 27 * 4))
        self.title.setWordWrap(True)
        self.title.setAlignment(Qt.AlignTop)
        self.title.setContextMenuPolicy(Qt.CustomContextMenu)
        self.title.customContextMenuRequested.connect(self.CopyTitle)

        # self.autor.setContextMenuPolicy(Qt.CustomContextMenu)
        # self.autor.customContextMenuRequested.connect(self.OpenAutor)

        layouy = self.horizontalLayout_4
        self.autorList = QtCategoryList(self)
        layouy.addWidget(QLabel("作者:"))
        layouy.addWidget(self.autorList)
        self.autorList.itemClicked.connect(self.ClickTagsItem)

        self.description.setContextMenuPolicy(Qt.CustomContextMenu)
        self.description.customContextMenuRequested.connect(
            self.CopyDescription)

        self.description.setGeometry(QRect(328, 240, 329, 27 * 4))
        self.description.setWordWrap(True)
        self.description.setAlignment(Qt.AlignTop)

        # self.categories.setGeometry(QRect(328, 240, 329, 27 * 4))
        # self.categories.setWordWrap(True)
        # self.categories.setAlignment(Qt.AlignTop)

        layouy = self.horizontalLayout_6
        self.categoriesList = QtCategoryList(self)
        layouy.addWidget(QLabel("分类:"))
        layouy.addWidget(self.categoriesList)
        self.categoriesList.itemClicked.connect(self.ClickCategoriesItem)

        # self.tags.setGeometry(QRect(328, 240, 329, 27 * 4))
        # self.tags.setWordWrap(True)
        # self.tags.setAlignment(Qt.AlignTop)

        layouy = self.horizontalLayout_7
        self.tagsList = QtCategoryList(self)
        layouy.addWidget(QLabel("Tags:"))
        layouy.addWidget(self.tagsList)
        self.tagsList.itemClicked.connect(self.ClickTagsItem)

        self.epsListWidget = QListWidget(self)
        self.epsListWidget.setFlow(self.epsListWidget.LeftToRight)
        self.epsListWidget.setWrapping(True)
        self.epsListWidget.setFrameShape(self.epsListWidget.NoFrame)
        self.epsListWidget.setResizeMode(self.epsListWidget.Adjust)

        self.epsLayout.addWidget(self.epsListWidget)

        self.listWidget = QtBookList(self, self.__class__.__name__)
        self.listWidget.InitUser(self.LoadNextPage)
        self.listWidget.doubleClicked.connect(self.OpenCommentInfo)

        self.childrenListWidget = QtBookList(None, self.__class__.__name__)
        self.childrenListWidget.InitUser(self.LoadChildrenNextPage)

        self.childrenWidget = QtWidgets.QWidget()
        layout = QHBoxLayout(self.childrenWidget)

        label = QLabel()
        label.setMinimumWidth(100)
        layout.addWidget(label)
        layout3 = QVBoxLayout()

        layout2 = QHBoxLayout()
        self.commentLine2 = QLineEdit()
        self.commentButton2 = QPushButton("回复")
        self.commentButton2.clicked.connect(self.SendCommentChildren)
        layout2.addWidget(self.commentLine2)
        layout2.addWidget(self.commentButton2)
        layout3.addLayout(layout2)
        layout3.addWidget(self.childrenListWidget)
        layout.addLayout(layout3)

        self.commentLayout.addWidget(self.listWidget)
        layout = QHBoxLayout()
        self.commentLine = QLineEdit()
        layout.addWidget(self.commentLine)
        self.commentButton = QPushButton("发送评论")
        layout.addWidget(self.commentButton)
        self.commentLayout.addLayout(layout, 1, 0)
        self.commentButton.clicked.connect(self.SendComment)

        # self.stackedWidget.addWidget(self.qtReadImg)
        self.epsListWidget.clicked.connect(self.OpenReadImg)

        self.closeFlag = self.__class__.__name__ + "-close"  # 切换book时,取消加载

    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        if self.stackedWidget.currentIndex() == 1:
            self.stackedWidget.setCurrentIndex(0)
            self.owner().qtReadImg.AddHistory()
            self.LoadHistory()
            a0.ignore()
        else:
            a0.accept()

    def CopyTitle(self):
        clipboard = QApplication.clipboard()
        clipboard.setText(self.title.text())
        self.msgForm.ShowMsg("复制标题")
        return

    # def OpenAutor(self):
    #     text = self.autor.text()
    #     self.owner().userForm.listWidget.setCurrentRow(0)
    #     self.owner().searchForm.searchEdit.setText(text)
    #     self.owner().searchForm.Search()
    #     return

    def Clear(self):
        self.stackedWidget.setCurrentIndex(0)
        self.owner().qtTask.CancelTasks(self.closeFlag)
        self.epsListWidget.clear()
        self.ClearCommnetList()

    def CopyDescription(self):
        clipboard = QApplication.clipboard()
        clipboard.setText(self.description.text())
        self.msgForm.ShowMsg("复制描述")
        return

    def OpenBook(self, bookId):
        self.bookId = bookId
        self.setWindowTitle(self.bookId)
        # if self.bookId in self.owner().downloadForm.downloadDict:
        #     self.download.setEnabled(False)
        # else:
        #     self.download.setEnabled(True)

        self.Clear()
        self.show()
        self.loadingForm.show()
        self.owner().qtTask.AddHttpTask(
            lambda x: BookMgr().AddBookById(bookId, x), self.OpenBookBack)

    def close(self):
        super(self.__class__, self).close()

    def OpenBookBack(self, msg):
        self.loadingForm.close()
        self.listWidget.UpdatePage(1, 1)
        self.childrenListWidget.UpdatePage(1, 1)
        self.childrenListWidget.UpdateState()
        self.listWidget.UpdateState()
        self.categoriesList.clear()
        self.tagsList.clear()
        self.autorList.clear()
        info = BookMgr().books.get(self.bookId)
        if msg == Status.Ok and info:
            # self.autor.setText(info.author)
            self.autorList.AddItem(info.author)
            self.title.setText(info.title)
            self.bookName = info.title
            self.description.setText(info.description)
            self.isFinished.setText("完本" if info.finished else "未完本")
            for name in info.categories:
                self.categoriesList.AddItem(name)
            # self.categories.setText(','.join(info.categories))
            # self.tags.setText(','.join(info.tags))
            for name in info.tags:
                self.tagsList.AddItem(name)
            self.likes.setText(str(info.totalLikes))
            self.views.setText(str(info.totalViews))

            if info.isFavourite:
                self.favorites.setEnabled(False)
            else:
                self.favorites.setEnabled(True)
            self.picture.setText("图片加载中...")
            fileServer = info.thumb.get("fileServer")
            path = info.thumb.get("path")
            name = info.thumb.get("originalName")
            self.url = fileServer
            self.path = path
            timeArray, day = ToolUtil.GetDateStr(info.updated_at)
            self.updateTick.setText(str(day) + "天前更新")
            if config.IsLoadingPicture:

                self.owner().qtTask.AddDownloadTask(
                    fileServer,
                    path,
                    completeCallBack=self.UpdatePicture,
                    cleanFlag=self.closeFlag)
            self.owner().qtTask.AddHttpTask(lambda x: Server().Send(
                req.GetComments(self.bookId), bakParam=x),
                                            self.GetCommnetBack,
                                            cleanFlag=self.closeFlag)

            self.owner().qtTask.AddHttpTask(
                lambda x: BookMgr().AddBookEpsInfo(self.bookId, x),
                self.GetEpsBack,
                cleanFlag=self.closeFlag)
            self.startRead.setEnabled(False)
        else:
            # QtWidgets.QMessageBox.information(self, '加载失败', msg, QtWidgets.QMessageBox.Yes)
            self.msgForm.ShowError(msg)
            self.hide()
        return

    def UpdatePicture(self, data, status):
        if status == Status.Ok:
            pic = QtGui.QPixmap()
            pic.loadFromData(data)
            pic.scaled(self.picture.size(), QtCore.Qt.KeepAspectRatio)
            self.picture.setPixmap(pic)
            # self.picture.setScaledContents(True)
            self.update()
        else:
            self.picture.setText("图片加载失败")
        return

    # 加载评论
    def GetCommnetBack(self, data):
        try:
            self.loadingForm.close()
            self.listWidget.UpdateState()
            msg = json.loads(data)
            if msg.get("code") == 200:
                comments = msg.get("data", {}).get("comments", {})
                topComments = msg.get("data", {}).get("topComments", [])
                page = int(comments.get("page", 1))
                pages = int(comments.get("pages", 1))
                limit = int(comments.get("limit", 1))
                self.listWidget.UpdatePage(page, pages)
                total = comments.get("total", 0)
                self.tabWidget.setTabText(1, "评论({})".format(str(total)))
                if page == 1:
                    for index, info in enumerate(topComments):
                        floor = "置顶"
                        content = info.get("content")
                        name = info.get("_user", {}).get("name")
                        avatar = info.get("_user", {}).get("avatar", {})
                        createdTime = info.get("created_at")
                        commentsCount = info.get("commentsCount")
                        commnetId = info.get('_id')
                        likesCount = info.get("likesCount")
                        self.listWidget.AddUserItem(commnetId, commentsCount,
                                                    likesCount, content, name,
                                                    createdTime, floor,
                                                    avatar.get("fileServer"),
                                                    avatar.get("path"),
                                                    avatar.get("originalName"))

                for index, info in enumerate(comments.get("docs")):
                    floor = total - ((page - 1) * limit + index)
                    content = info.get("content")
                    name = info.get("_user", {}).get("name")
                    avatar = info.get("_user", {}).get("avatar", {})
                    createdTime = info.get("created_at")
                    commentsCount = info.get("commentsCount")
                    commnetId = info.get('_id')
                    likesCount = info.get("likesCount")
                    self.listWidget.AddUserItem(commnetId, commentsCount,
                                                likesCount, content, name,
                                                createdTime, floor,
                                                avatar.get("fileServer"),
                                                avatar.get("path"),
                                                avatar.get("originalName"))
            return
        except Exception as es:
            Log.Error(es)

    def GetEpsBack(self, st):
        if st == Status.Ok:
            self.UpdateEpsData()
            self.lastEpsId = -1
            self.LoadHistory()
            return
        return

    def UpdateEpsData(self):
        self.epsListWidget.clear()
        info = BookMgr().books.get(self.bookId)
        if not info:
            return
        self.startRead.setEnabled(True)
        downloadIds = self.owner().downloadForm.GetDownloadCompleteEpsId(
            self.bookId)
        for index, epsInfo in enumerate(info.eps):
            label = QLabel(epsInfo.title)
            label.setContentsMargins(20, 10, 20, 10)
            item = QListWidgetItem(self.epsListWidget)
            if index in downloadIds:
                item.setBackground(QColor(18, 161, 130))
            else:
                item.setBackground(QColor(0, 0, 0, 0))
            item.setSizeHint(label.sizeHint())
            self.epsListWidget.setItemWidget(item, label)
        self.tabWidget.setTabText(0, "章节({})".format(str(len(info.eps))))
        return

    def AddDownload(self):
        self.owner().epsInfoForm.OpenEpsInfo(self.bookId)
        # if self.owner().downloadForm.AddDownload(self.bookId):
        #     QtBubbleLabel.ShowMsgEx(self, "添加下载成功")
        # else:
        #     QtBubbleLabel.ShowMsgEx(self, "已在下载列表")
        # self.download.setEnabled(False)

    def AddFavority(self):
        User().AddAndDelFavorites(self.bookId)
        QtBubbleLabel.ShowMsgEx(self, "添加收藏成功")
        self.favorites.setEnabled(False)

    def LoadNextPage(self):
        self.loadingForm.show()
        self.owner().qtTask.AddHttpTask(lambda x: Server(
        ).Send(req.GetComments(self.bookId, self.listWidget.page + 1),
               bakParam=x),
                                        self.GetCommnetBack,
                                        cleanFlag=self.closeFlag)
        return

    def OpenReadImg(self, modelIndex):
        index = modelIndex.row()
        self.OpenReadIndex(index)

    def OpenReadIndex(self, index):
        item = self.epsListWidget.item(index)
        if not item:
            return
        widget = self.epsListWidget.itemWidget(item)
        if not widget:
            return
        name = widget.text()
        self.hide()
        self.owner().qtReadImg.OpenPage(self.bookId, index, name)
        # self.stackedWidget.setCurrentIndex(1)

    def StartRead(self):
        if self.lastEpsId >= 0:
            self.OpenReadIndex(self.lastEpsId)
        else:
            self.OpenReadIndex(0)
        return

    def LoadHistory(self):
        info = self.owner().historyForm.GetHistory(self.bookId)
        if not info:
            self.startRead.setText("观看第{}章".format(str(1)))
            return
        if self.lastEpsId == info.epsId:
            self.startRead.setText("观看第{}章".format(str(self.lastEpsId + 1)))
            return

        if self.lastEpsId >= 0:
            item = self.epsListWidget.item(self.lastEpsId)
            if item:
                downloadIds = self.owner(
                ).downloadForm.GetDownloadCompleteEpsId(self.bookId)
                if self.lastEpsId in downloadIds:
                    item.setBackground(QColor(18, 161, 130))
                else:
                    item.setBackground(QColor(0, 0, 0, 0))

        item = self.epsListWidget.item(info.epsId)
        if not item:
            return
        item.setBackground(QColor(238, 162, 164))
        self.epsListWidget.update()
        self.lastEpsId = info.epsId
        self.startRead.setText("观看第{}章".format(str(self.lastEpsId + 1)))

    def ClickCategoriesItem(self, item):
        text = item.text()
        self.owner().userForm.listWidget.setCurrentRow(1)
        self.owner().searchForm.searchEdit.setText("")
        self.owner().searchForm.OpenSearchCategories(text)
        return

    def ClickTagsItem(self, item):
        text = item.text()
        self.owner().userForm.listWidget.setCurrentRow(1)
        self.owner().searchForm.searchEdit.setText(text)
        self.owner().searchForm.Search()
        return

    def SendComment(self):
        data = self.commentLine.text()
        if not data:
            return
        self.commentLine.setText("")
        self.loadingForm.show()
        self.owner().qtTask.AddHttpTask(lambda x: Server().Send(
            req.SendComment(self.bookId, data), bakParam=x),
                                        callBack=self.SendCommentBack)

    def SendCommentBack(self, msg):
        try:
            data = json.loads(msg)
            if data.get("code") == 200:
                self.ClearCommnetList()
                self.owner().qtTask.AddHttpTask(lambda x: Server().Send(
                    req.GetComments(self.bookId), bakParam=x),
                                                self.GetCommnetBack,
                                                cleanFlag=self.closeFlag)
            else:
                self.loadingForm.close()
                QtBubbleLabel.ShowErrorEx(self, data.get("message", "错误"))
            self.commentLine.setText("")
        except Exception as es:
            self.loadingForm.close()
            Log.Error(es)

    def OpenCommentInfo(self, modelIndex):
        index = modelIndex.row()
        item = self.listWidget.item(index)
        if not item:
            return
        widget = self.listWidget.itemWidget(item)
        if not widget:
            return

        self.childrenListWidget.clear()
        self.childrenListWidget.UpdatePage(1, 1)
        self.childrenListWidget.UpdateState()
        if self.childrenListWidget.parentId == index:
            # self.childrenWidget.hide()
            self.childrenWidget.setParent(None)
            widget.gridLayout.removeWidget(self.childrenWidget)
            self.childrenListWidget.parentId = -1
            item.setSizeHint(widget.sizeHint())
            return
        if self.childrenListWidget.parentId >= 0:
            item2 = self.listWidget.item(self.childrenListWidget.parentId)
            widget2 = self.listWidget.itemWidget(item2)
            self.childrenWidget.setParent(None)
            widget2.gridLayout.removeWidget(self.childrenWidget)
            self.childrenListWidget.parentId = -1
            item2.setSizeHint(widget2.sizeHint())

        self.loadingForm.show()
        self.owner().qtTask.AddHttpTask(lambda x: Server().Send(
            req.GetCommentsChildrenReq(widget.id), bakParam=x),
                                        self.LoadCommentInfoBack,
                                        backParam=index,
                                        cleanFlag=self.closeFlag)

    def LoadCommentInfoBack(self, msg, index):
        try:
            self.loadingForm.close()
            item = self.listWidget.item(index)
            if not item:
                return
            widget = self.listWidget.itemWidget(item)
            if not widget:
                return
            self.childrenListWidget.UpdateState()
            data = json.loads(msg)
            self.childrenListWidget.parentId = index
            widget.gridLayout.addWidget(self.childrenWidget, 1, 0, 1, 1)
            if data.get("code") == 200:
                comments = data.get("data", {}).get("comments", {})
                page = int(comments.get("page", 1))
                total = int(comments.get("total", 1))
                pages = int(comments.get("pages", 1))
                limit = int(comments.get("limit", 1))
                self.childrenListWidget.UpdatePage(page, pages)
                for index, info in enumerate(comments.get("docs")):
                    floor = total - ((page - 1) * limit + index)
                    content = info.get("content")
                    name = info.get("_user", {}).get("name")
                    avatar = info.get("_user", {}).get("avatar", {})
                    createdTime = info.get("created_at")
                    commentsCount = info.get("commentsCount")
                    likesCount = info.get("likesCount")
                    commnetId = info.get('_id')
                    self.childrenListWidget.AddUserItem(
                        commnetId, commentsCount, likesCount, content, name,
                        createdTime, floor, avatar.get("fileServer"),
                        avatar.get("path"), avatar.get("originalName"))

                pass
            self.listWidget.scrollToItem(
                item, self.listWidget.ScrollHint.PositionAtTop)
            size = self.listWidget.size()
            item.setSizeHint(size)
        except Exception as es:
            Log.Error(es)

    def SendCommentChildren(self):
        data = self.commentLine2.text()
        if not data:
            return
        index = self.childrenListWidget.parentId
        item = self.listWidget.item(index)
        if not item:
            return
        widget = self.listWidget.itemWidget(item)
        if not widget:
            return
        self.commentLine2.setText("")
        commentId = widget.id
        self.loadingForm.show()
        self.childrenListWidget.clear()
        self.owner().qtTask.AddHttpTask(lambda x: Server().Send(
            req.SendCommentChildrenReq(commentId, data), bakParam=x),
                                        callBack=self.SendCommentChildrenBack,
                                        backParam=index)

    def SendCommentChildrenBack(self, msg, index):
        try:
            item = self.listWidget.item(index)
            if not item:
                self.loadingForm.close()
                return
            widget = self.listWidget.itemWidget(item)
            if not widget:
                self.loadingForm.close()
                return

            data = json.loads(msg)
            if data.get("code") == 200:
                self.owner().qtTask.AddHttpTask(lambda x: Server().Send(
                    req.GetCommentsChildrenReq(widget.id), bakParam=x),
                                                self.LoadCommentInfoBack,
                                                backParam=index,
                                                cleanFlag=self.closeFlag)
            else:
                self.loadingForm.close()
                QtBubbleLabel.ShowErrorEx(self, data.get("message", "错误"))
            self.commentLine.setText("")
        except Exception as es:
            self.loadingForm.close()
            Log.Error(es)

    def LoadChildrenNextPage(self):
        index = self.childrenListWidget.parentId
        item = self.listWidget.item(index)
        if not item:
            return
        widget = self.listWidget.itemWidget(item)
        if not widget:
            return
        self.loadingForm.show()
        self.owner().qtTask.AddHttpTask(
            lambda x: Server().Send(req.GetCommentsChildrenReq(
                widget.id, self.childrenListWidget.page + 1),
                                    bakParam=x),
            self.LoadCommentInfoBack,
            backParam=index,
            cleanFlag=self.closeFlag)
        return

    def ClearCommnetList(self):
        if self.childrenListWidget.parentId >= 0:
            item2 = self.listWidget.item(self.childrenListWidget.parentId)
            widget2 = self.listWidget.itemWidget(item2)
            self.childrenWidget.setParent(None)
            widget2.gridLayout.removeWidget(self.childrenWidget)
            self.childrenListWidget.parentId = -1
            item2.setSizeHint(widget2.sizeHint())
        self.childrenListWidget.clear()
        self.listWidget.clear()

    def eventFilter(self, obj, event):
        if event.type() == QEvent.MouseButtonPress:
            if event.button() == Qt.LeftButton:
                if obj.pixmap() and not obj.text():
                    QtImgMgr().ShowImg(obj.pixmap())
                return True
            else:
                return False
        else:
            return super(self.__class__, self).eventFilter(obj, event)
class MainWidget(QWidget):

    # CONSTANTS
    EMPTY_STRING = ""

    # TOGGLE BUTTON CONSTANTS
    BUTTON_CLOSED_ICON_PATH = 'resources/menu_closed_button_icon.png'
    BUTTON_OPENED_ICON_PATH = 'resources/menu_opened_button_icon.png'

    TOOGLE_BUTTON_CSS_PROPERTY = "QPushButton {background-color: rgb(1,150,250); border:  none ; qproperty-iconSize: 80px}"
    CURRENT_PATH_LINE_EDIT_PROPERTY = "QLineEdit {background-color: rgba(240, 240, 240, 1);}"

    TOOGLE_CLOSED_COLOR = "background-color: rgb(1,150,250);"
    TOOGLE_OPENED_COLOR = "background-color: rgba(44, 53, 57, 0.2);"

    WHITE = "background-color: rgb(255, 255, 255);"

    FRAME_BUTTON_STYLE = "background-color: rgb(0, 191, 255); color: rgb(255, 255, 255);"
    FRAME_LINE_EDIT_STYLE = "background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);"
    FRAME_LABEL_STYLE = "QLabel { background-color : rgba(44, 53, 57, 0); }"

    SEARCH_ICON_STYLE = "QPushButton {background-color: rgb(1,150,250);}"
    BACK_ICON_STYLE = "QPushButton {background-color: rgb(1,150,250);} QPushButton:pressed {background-color: rgb(40,170,250);}"

    WIDTH = 1440
    HEIGHT = 900

    # Size of the operations widget buttons
    OPERATION_BUTTON_WIDTH = 40
    OPERATION_BUTTON_HEIGHT = 40

    FILES_LIST_VIEW_WIDTH = 820
    FILES_LIST_VIEW_HEIGHT = 680

    TOGGLE_BUTTON_ANIMATION_DURATION = 200
    RIGHT_MENU_ANIMATION_DURATION = 250

    # ICONS PATHS

    # Actions icons
    ADD_FILE_ICON_PATH = "resources/add_file_icon.png"
    ADD_DIRECTORY_ICON_PATH = "resources/add_directory_icon.png"
    COPY_ELEMENT_ICON_PATH = "resources/copy_element_icon.png"
    MOVE_ELEMENT_ICON_PATH = "resources/move_element_icon.png"
    DELETE_ELEMENT_ICON_PATH = "resources/delete_element_icon.png"
    SEARCH_ICON_PATH = "resources/search_icon_white.png"
    CREATE_ARCHIVE_ICON_PATH = "resources/create_archive_icon.png"
    UNARCHIVE_FILE_ICON_PATH = "resources/unarchive_file_icon.png"
    RENAME_ELEMENT_ICON_PATH = "resources/rename_icon_white.png"
    BACK_ICON_PATH = "resources/back_icon.png"

    # Elements icons
    FILE_ICON_PATH = "resources/file_icon.png"
    FOLDER_ICON_PATH = "resources/folder_icon.png"
    ZIP_ICON_PATH = "resources/zip_icon.png"

    # Tooltips
    COPY_TOOLTIP = "Copy files / folders"
    MOVE_TOOLTIP = "Move files / folders"
    DELETE_TOOLTIP = "Delete files / folders"
    ARCHIVE_TOOLTIP = "Archive files / folders"
    UNARCHIVE_TOOLTIP = "Unarchive files / folders"
    CREATE_FILE_TOOLTIP = "Create a new text file"
    CREATE_DIRECTORY_TOOLTIP = "Create a new folder"
    RENAME_TOOLTIP = "Rename a file / folder"
    BACK_TOOLTIP = "Move up one directory"

    # Buttons name
    COPY = "Copy"
    MOVE = "Move"
    DELETE = "Delete"
    ARCHIVE = "Archive"
    UNARCHIVE = "Unarchive"
    RENAME = "Rename"
    CREATE_FILE = "Create file"
    CREATE_FOLDER = "Create folder"

    # Labels
    SELECTED_ITEMS_TEXT = "Selected items:"
    ARCHIVE_NAME_TEXT = "Archive name:"
    CREATE_FILE_NAME_TEXT = "File name:"
    CREATE_FOLDER_NAME_TEXT = "Folder name:"
    RENAME_ELEMENT_TEXT = "New name:"

    def __init__(self, parent, model, controller):
        super(MainWidget, self).__init__(parent)

        self._model = model
        self._controller = controller

        # FILES LIST VIEW

        self.filesListView = FilesListView(self.FILES_LIST_VIEW_WIDTH,
                                           self.FILES_LIST_VIEW_HEIGHT,
                                           self._model, self._controller, self)
        self.filesListView.move(230, 120)

        # TREE VIEW FOR SYSTEM DIRECTORY HIERARCHY
        self.treeView = TreeView(self._model, self._controller, self)
        self.treeView.setFixedSize(200, 820)
        self.treeView.move(0, 60)

        # DISC SELECTION COMBO BOX
        self.discSelectionComboBox = QComboBox(self)
        self.discSelectionComboBox.setFixedSize(100, 30)
        self.discSelectionComboBox.move(230, 60)
        self.discSelectionComboBox.addItems(self._model.combo_box_list)

        # CONNECT WIDGETS TO CONTROLLER
        self.discSelectionComboBox.currentTextChanged.connect(
            self._controller.change_combo_box_selection)

        # LISTEN FOR MODEL EVENT SIGNALS
        self._model.combo_box_selection_changed.connect(
            self.on_combo_box_selection_changed)

        self.frameRightMenu = QWidget(self)
        self.frameRightMenu.setFixedSize(360, self.HEIGHT)
        self.frameRightMenu.move(1450, 15)
        self.frameRightMenu.setStyleSheet(self.TOOGLE_CLOSED_COLOR)

        # BUTTON WHICH TOOGLE ON/OFF THE TREE VIEW CONTAINING THE SELECTED ITEMS TREE VIEW
        self.toggleButton = QPushButton(QIcon(self.BUTTON_CLOSED_ICON_PATH),
                                        self.EMPTY_STRING, self)
        self.toggleButton.setFixedSize(100, 70)
        self.toggleButton.move(1300, 0)
        self.toggleButton.setStyleSheet(self.TOOGLE_BUTTON_CSS_PROPERTY)

        self._enable = True

        self.toggleButton.clicked.connect(
            lambda: Animations.toggleMenu(self, self._enable))

        # Label that shows "Selected items:"
        self.selectedItemsLabel = QLabel(self.SELECTED_ITEMS_TEXT,
                                         self.frameRightMenu)
        self.selectedItemsLabel.move(100, 20)
        self.selectedItemsLabel.setStyleSheet(self.FRAME_LABEL_STYLE)

        # The list with selected elements from FilesListView
        self.selectedFilesListWidget = QListWidget(self.frameRightMenu)
        self.selectedFilesListWidget.setFixedSize(320, 500)
        self.selectedFilesListWidget.move(23, 60)
        self.selectedFilesListWidget.setStyleSheet(self.WHITE)

        # ACTIONS BUTTONS

        # Copy button
        self.copyElementButton = OperationsWidgetButton(
            QIcon(self.COPY_ELEMENT_ICON_PATH), self.EMPTY_STRING, self)
        self.copyElementButton.clicked.connect(self.doCopy)
        self.copyElementButton.move(230, 0)
        self.copyElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH,
                                            self.OPERATION_BUTTON_HEIGHT)
        self.copyElementButton.setToolTip(self.COPY_TOOLTIP)

        # Move button
        self.moveElementButton = OperationsWidgetButton(
            QIcon(self.MOVE_ELEMENT_ICON_PATH), self.EMPTY_STRING, self)
        self.moveElementButton.clicked.connect(self.doMove)
        self.moveElementButton.move(290, 0)
        self.moveElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH,
                                            self.OPERATION_BUTTON_HEIGHT)
        self.moveElementButton.setToolTip(self.MOVE_TOOLTIP)

        # Delete button
        self.deleteElementButton = OperationsWidgetButton(
            QIcon(self.DELETE_ELEMENT_ICON_PATH), self.EMPTY_STRING, self)
        self.deleteElementButton.clicked.connect(self.doDelete)
        self.deleteElementButton.move(350, 0)
        self.deleteElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH,
                                              self.OPERATION_BUTTON_HEIGHT)
        self.deleteElementButton.setToolTip(self.DELETE_TOOLTIP)

        # Archive button
        self.archiveElementButton = OperationsWidgetButton(
            QIcon(self.CREATE_ARCHIVE_ICON_PATH), self.EMPTY_STRING, self)
        self.archiveElementButton.clicked.connect(self.doArchive)
        self.archiveElementButton.move(410, 0)
        self.archiveElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH,
                                               self.OPERATION_BUTTON_HEIGHT)
        self.archiveElementButton.setToolTip(self.ARCHIVE_TOOLTIP)

        # Unarchive button
        self.unarchiveElementButton = OperationsWidgetButton(
            QIcon(self.UNARCHIVE_FILE_ICON_PATH), self.EMPTY_STRING, self)
        self.unarchiveElementButton.clicked.connect(self.doUnarchive)
        self.unarchiveElementButton.move(470, 0)
        self.unarchiveElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH,
                                                 self.OPERATION_BUTTON_HEIGHT)
        self.unarchiveElementButton.setToolTip(self.UNARCHIVE_TOOLTIP)

        # Add file button
        self.addFileButton = OperationsWidgetButton(
            QIcon(self.ADD_FILE_ICON_PATH), self.EMPTY_STRING, self)
        self.addFileButton.clicked.connect(self.doCreateFile)
        self.addFileButton.move(530, 0)
        self.addFileButton.setFixedSize(self.OPERATION_BUTTON_WIDTH,
                                        self.OPERATION_BUTTON_HEIGHT)
        self.addFileButton.setToolTip(self.CREATE_FILE_TOOLTIP)

        # Add directory button
        self.addDirectoryButton = OperationsWidgetButton(
            QIcon(self.ADD_DIRECTORY_ICON_PATH), self.EMPTY_STRING, self)
        self.addDirectoryButton.clicked.connect(self.doCreateFolder)
        self.addDirectoryButton.move(590, 0)
        self.addDirectoryButton.setFixedSize(self.OPERATION_BUTTON_WIDTH,
                                             self.OPERATION_BUTTON_HEIGHT)
        self.addDirectoryButton.setToolTip(self.CREATE_DIRECTORY_TOOLTIP)

        # Move button
        self.renameElementButton = OperationsWidgetButton(
            QIcon(self.RENAME_ELEMENT_ICON_PATH), self.EMPTY_STRING, self)
        self.renameElementButton.clicked.connect(self.doRename)
        self.renameElementButton.move(650, 0)
        self.renameElementButton.setFixedSize(self.OPERATION_BUTTON_WIDTH,
                                              self.OPERATION_BUTTON_HEIGHT)
        self.renameElementButton.setToolTip(self.RENAME_TOOLTIP)

        # Text field needed for displaying the current path
        self.currentPathLineEdit = QLineEdit(self.EMPTY_STRING, self)
        self.currentPathLineEdit.move(350, 80)
        self.currentPathLineEdit.setFixedSize(400, 27)
        self.currentPathLineEdit.setStyleSheet(
            self.CURRENT_PATH_LINE_EDIT_PROPERTY)
        self.currentPathLineEdit.setReadOnly(True)
        self.currentPathLineEdit.setText(self._model.current_path)
        self.currentPathLineEdit.textChanged.connect(
            self._controller.change_current_path_text)

        self._model.current_path_changed.connect(self.on_current_path_changed)

        # Text field needed for searching file / folder by the name
        self.searchLineEdit = QLineEdit(self.EMPTY_STRING, self)
        self.searchLineEdit.move(810, 80)
        self.searchLineEdit.setFixedSize(200, 27)
        self.searchLineEdit.textChanged.connect(
            self._controller.change_search_text)

        self._model.current_search_changed.connect(
            self.on_current_search_changed)

        self.searchIconButton = OperationsWidgetButton(
            QIcon(self.SEARCH_ICON_PATH), self.EMPTY_STRING, self)
        self.searchIconButton.move(1015, 78)
        self.searchIconButton.setFixedSize(30, 30)
        self.searchIconButton.setStyleSheet(self.SEARCH_ICON_STYLE)
        self.searchIconButton.setEnabled(False)

        self.backButton = OperationsWidgetButton(QIcon(self.BACK_ICON_PATH),
                                                 self.EMPTY_STRING, self)
        self.backButton.clicked.connect(self.doBack)
        self.backButton.move(765, 80)
        self.backButton.setFixedSize(25, 25)
        self.backButton.setStyleSheet(self.BACK_ICON_STYLE)
        self.backButton.setToolTip(self.BACK_TOOLTIP)
        self.backButton.setEnabled(True)

        # ACTIONS LABELS
        self.archiveLabel = QLabel(self.ARCHIVE_NAME_TEXT, self.frameRightMenu)
        self.createFolderLabel = QLabel(self.CREATE_FOLDER_NAME_TEXT,
                                        self.frameRightMenu)
        self.createFileLabel = QLabel(self.CREATE_FILE_NAME_TEXT,
                                      self.frameRightMenu)
        self.renameElementLabel = QLabel(self.RENAME_ELEMENT_TEXT,
                                         self.frameRightMenu)

        # ACTIONS LINE EDITS
        self.archiveNameEditLine = QLineEdit(self.EMPTY_STRING,
                                             self.frameRightMenu)
        self.createFileEditLine = QLineEdit(self.EMPTY_STRING,
                                            self.frameRightMenu)
        self.createFolderEditLine = QLineEdit(self.EMPTY_STRING,
                                              self.frameRightMenu)
        self.renameElementEditLine = QLineEdit(self.EMPTY_STRING,
                                               self.frameRightMenu)

        # ACTIONS BUTTONS
        self.copyButton = ToggleMenuButton(self.COPY, self.frameRightMenu)
        self.moveButton = ToggleMenuButton(self.MOVE, self.frameRightMenu)
        self.deleteButton = ToggleMenuButton(self.DELETE, self.frameRightMenu)
        self.archiveButton = ToggleMenuButton(self.ARCHIVE,
                                              self.frameRightMenu)
        self.unarchiveButton = ToggleMenuButton(self.UNARCHIVE,
                                                self.frameRightMenu)
        self.createFileButton = ToggleMenuButton(self.CREATE_FILE,
                                                 self.frameRightMenu)
        self.createFolderButton = ToggleMenuButton(self.CREATE_FOLDER,
                                                   self.frameRightMenu)
        self.renameElementButton = ToggleMenuButton(self.RENAME,
                                                    self.frameRightMenu)

        self.__createFrameLayoutElements()

    @Slot(str)
    def on_current_path_changed(self, path):
        self._model.elements_list.clear()
        self._model.selected_items.clear()
        self.selectedFilesListWidget.clear()
        self._model.elements_list = Directory.get_all_subelements(path)
        self.filesListView.model().populateList()

    @Slot(str)
    def on_current_search_changed(self, name):
        print(name)

    def removeFromSelectedItems(self, item):
        Animations.toggleMenu(self, True)
        count = self.selectedFilesListWidget.count()
        index = 0

        for i in range(count):
            if item.text() == self.selectedFilesListWidget.item(i).text():
                index = i
                break

        self.selectedFilesListWidget.takeItem(index)

    def appendToSelectedItems(self, item):
        Animations.toggleMenu(self, True)
        listItem = ListWidgetItem(item)
        self.selectedFilesListWidget.insertItem(0, listItem)

    def setCurrentPath(self, path):
        self.currentPathLineEdit.setText(path)

    @Slot(str)
    def on_combo_box_selection_changed(self, value):
        index = self.discSelectionComboBox.findText(value)
        self.discSelectionComboBox.setCurrentIndex(index)

    Slot()

    def doBack(self):
        path = self.currentPathLineEdit.text()
        parentPath = os.path.dirname(path)
        self.setCurrentPath(parentPath)

    @Slot()
    def doCopy(self):
        self.__setCopyLayout(True)
        Animations.toggleMenu(self, True)

    @Slot()
    def doMove(self):
        self.__setMoveLayout(True)
        Animations.toggleMenu(self, True)

    @Slot()
    def doDelete(self):
        self.__setDeleteLayout(True)
        Animations.toggleMenu(self, True)

    @Slot()
    def doArchive(self):
        self.__setArchiveLayout(True)
        Animations.toggleMenu(self, True)

    @Slot()
    def doUnarchive(self):
        self.__setUnarchiveLayout(True)
        Animations.toggleMenu(self, True)

    @Slot()
    def doCreateFile(self):
        self.__setCreateFileLayout(True)
        Animations.toggleMenu(self, True)

    @Slot()
    def doCreateFolder(self):
        self.__setCreateFolderLayout(True)
        Animations.toggleMenu(self, True)

    @Slot()
    def doRename(self):
        self.__setRenameLayout(True)
        Animations.toggleMenu(self, True)

    # Method that creates all layout object from the frame layout
    def __createFrameLayoutElements(self):

        # =================   COPY ACTION  =======================
        # Copy button on right frame
        self.copyButton.setStyleSheet(self.FRAME_BUTTON_STYLE)
        self.copyButton.move(120, 600)
        self.copyButton.setFixedSize(120, 32)
        self.copyButton.setVisible(False)

        # =================   MOVE ACTION  =======================
        # Move button on right frame
        self.moveButton.setStyleSheet(self.FRAME_BUTTON_STYLE)
        self.moveButton.move(120, 600)
        self.moveButton.setFixedSize(120, 32)
        self.moveButton.setVisible(False)

        # =================   DELETE ACTION  =======================
        # Delete button on right frame
        self.deleteButton.setStyleSheet(self.FRAME_BUTTON_STYLE)
        self.deleteButton.move(120, 600)
        self.deleteButton.setFixedSize(120, 32)
        self.deleteButton.setVisible(False)

        # =================   UNARCHIVE ACTION  =======================
        # Unarchive button on right frame
        self.unarchiveButton.setStyleSheet(self.FRAME_BUTTON_STYLE)
        self.unarchiveButton.move(120, 600)
        self.unarchiveButton.setFixedSize(120, 32)
        self.unarchiveButton.setVisible(False)

        # =================   ARCHIVE ACTION  =======================

        self.archiveLabel.move(100, 590)
        self.archiveLabel.setStyleSheet(self.FRAME_LABEL_STYLE)
        self.archiveLabel.setVisible(False)

        self.archiveNameEditLine.move(55, 620)
        self.archiveNameEditLine.setFixedSize(250, 30)
        self.archiveNameEditLine.setStyleSheet(self.FRAME_LINE_EDIT_STYLE)
        self.archiveNameEditLine.setVisible(False)

        self.archiveButton.setStyleSheet(self.FRAME_BUTTON_STYLE)
        self.archiveButton.move(120, 700)
        self.archiveButton.setFixedSize(120, 32)
        self.archiveButton.setVisible(False)

        # =================   CREATE NEW FILE ACTION  =======================

        self.createFileLabel.move(120, 590)
        self.createFileLabel.setStyleSheet(self.FRAME_LABEL_STYLE)
        self.createFileLabel.setVisible(False)

        self.createFileEditLine.move(55, 620)
        self.createFileEditLine.setFixedSize(250, 30)
        self.createFileEditLine.setStyleSheet(self.FRAME_LINE_EDIT_STYLE)
        self.createFileEditLine.setVisible(False)

        self.createFileButton.setStyleSheet(self.FRAME_BUTTON_STYLE)
        self.createFileButton.move(120, 700)
        self.createFileButton.setFixedSize(120, 32)
        self.createFileButton.setVisible(False)

        # =================   CREATE NEW FOLDER ACTION  =======================

        self.createFolderLabel.move(120, 590)
        self.createFolderLabel.setStyleSheet(self.FRAME_LABEL_STYLE)
        self.createFolderLabel.setVisible(False)

        self.createFolderEditLine.move(55, 620)
        self.createFolderEditLine.setFixedSize(250, 30)
        self.createFolderEditLine.setStyleSheet(self.FRAME_LINE_EDIT_STYLE)
        self.createFolderEditLine.setVisible(False)

        self.createFolderButton.setStyleSheet(self.FRAME_BUTTON_STYLE)
        self.createFolderButton.move(120, 700)
        self.createFolderButton.setFixedSize(120, 32)
        self.createFolderButton.setVisible(False)

        # =================  RENAME ELEMENT ACTION  =======================

        self.renameElementLabel.move(120, 590)
        self.renameElementLabel.setStyleSheet(self.FRAME_LABEL_STYLE)
        self.renameElementLabel.setVisible(False)

        self.renameElementEditLine.move(55, 620)
        self.renameElementEditLine.setFixedSize(250, 30)
        self.renameElementEditLine.setStyleSheet(self.FRAME_LINE_EDIT_STYLE)
        self.renameElementEditLine.setVisible(False)

        self.renameElementButton.setStyleSheet(self.FRAME_BUTTON_STYLE)
        self.renameElementButton.move(120, 700)
        self.renameElementButton.setFixedSize(120, 32)
        self.renameElementButton.setVisible(False)

    # Method that sets the frame layout for rename operation
    def __setRenameLayout(self, shown):

        if shown == True:
            self.renameElementLabel.setVisible(True)
            self.renameElementEditLine.setVisible(True)
            self.renameElementButton.setVisible(True)

            self.__setCopyLayout(False)
            self.__setDeleteLayout(False)
            self.__setMoveLayout(False)
            self.__setCreateFileLayout(False)
            self.__setCreateFolderLayout(False)
            self.__setArchiveLayout(False)
            self.__setUnarchiveLayout(False)

        else:
            self.renameElementLabel.setVisible(False)
            self.renameElementEditLine.setVisible(False)
            self.renameElementButton.setVisible(False)

    # Method that sets the frame layout for archive operation
    def __setCreateFileLayout(self, shown):

        if shown == True:
            self.createFileLabel.setVisible(True)
            self.createFileEditLine.setVisible(True)
            self.createFileButton.setVisible(True)

            self.__setCopyLayout(False)
            self.__setDeleteLayout(False)
            self.__setMoveLayout(False)
            self.__setRenameLayout(False)
            self.__setCreateFolderLayout(False)
            self.__setArchiveLayout(False)
            self.__setUnarchiveLayout(False)

        else:
            self.createFileLabel.setVisible(False)
            self.createFileEditLine.setVisible(False)
            self.createFileButton.setVisible(False)

    # Method that sets the frame layout for archive operation
    def __setCreateFolderLayout(self, shown):

        if shown == True:
            self.createFolderLabel.setVisible(True)
            self.createFolderEditLine.setVisible(True)
            self.createFolderButton.setVisible(True)

            self.__setCopyLayout(False)
            self.__setDeleteLayout(False)
            self.__setMoveLayout(False)
            self.__setRenameLayout(False)
            self.__setCreateFileLayout(False)
            self.__setArchiveLayout(False)
            self.__setUnarchiveLayout(False)

        else:
            self.createFolderLabel.setVisible(False)
            self.createFolderEditLine.setVisible(False)
            self.createFolderButton.setVisible(False)

    # Method that sets the frame layout for archive operation
    def __setArchiveLayout(self, shown):

        if shown == True:
            self.archiveLabel.setVisible(True)
            self.archiveNameEditLine.setVisible(True)
            self.archiveButton.setVisible(True)

            self.__setCopyLayout(False)
            self.__setDeleteLayout(False)
            self.__setMoveLayout(False)
            self.__setRenameLayout(False)
            self.__setCreateFileLayout(False)
            self.__setCreateFolderLayout(False)
            self.__setUnarchiveLayout(False)

        else:
            self.archiveLabel.setVisible(False)
            self.archiveNameEditLine.setVisible(False)
            self.archiveButton.setVisible(False)

    # Method that sets the frame layout for copy operation
    def __setCopyLayout(self, shown):

        if shown == True:
            self.copyButton.setVisible(True)
            self.__setMoveLayout(False)
            self.__setDeleteLayout(False)
            self.__setRenameLayout(False)
            self.__setCreateFileLayout(False)
            self.__setCreateFolderLayout(False)
            self.__setArchiveLayout(False)
            self.__setUnarchiveLayout(False)

        else:
            self.copyButton.setVisible(False)

    # Method that sets the frame layout for move operation
    def __setMoveLayout(self, shown):

        if shown == True:
            self.moveButton.setVisible(True)

            self.__setDeleteLayout(False)
            self.__setCopyLayout(False)
            self.__setRenameLayout(False)
            self.__setCreateFileLayout(False)
            self.__setCreateFolderLayout(False)
            self.__setArchiveLayout(False)
            self.__setUnarchiveLayout(False)

        else:
            self.moveButton.setVisible(False)

    # Method that sets the frame layout for delete operation
    def __setDeleteLayout(self, shown):

        if shown == True:
            self.deleteButton.setVisible(True)

            self.__setCopyLayout(False)
            self.__setMoveLayout(False)
            self.__setRenameLayout(False)
            self.__setCreateFileLayout(False)
            self.__setCreateFolderLayout(False)
            self.__setArchiveLayout(False)
            self.__setUnarchiveLayout(False)

        else:
            self.deleteButton.setVisible(False)

    # Method that sets the frame layout for unarchive operation
    def __setUnarchiveLayout(self, shown):

        if shown == True:
            self.unarchiveButton.setVisible(True)

            self.__setCopyLayout(False)
            self.__setMoveLayout(False)
            self.__setRenameLayout(False)
            self.__setCreateFileLayout(False)
            self.__setCreateFolderLayout(False)
            self.__setArchiveLayout(False)
            self.__setDeleteLayout(False)

        else:
            self.unarchiveButton.setVisible(False)