Пример #1
0
class settingPage(QDialog):
    settingSignal = Signal(dict)

    def __init__(self):
        super().__init__()
        self.settingDict = {'tableRefresh': 0,  # 0: 开启, 1: 关闭
                            'tableRefreshFPS': 0,  # 0: 60FPS, 1: 30FPS, 2: 20FPS, 3: 10FPS
                            'graphRefreshFPS': 1,  # 0: 60FPS, 1: 30FPS, 2: 20FPS, 3: 10FPS
                            }

        self.setWindowTitle('设置')
        self.resize(300, 200)
        layout = QGridLayout()
        self.setLayout(layout)

        if os.path.exists('config'):  # 导入已存在的设置
            with open('config', 'r') as cfg:
                for line in cfg:
                    if '=' in line:
                        try:
                            cfgName, cfgValue = line.strip().replace(' ', '').split('=')
                            self.settingDict[cfgName] = cfgValue
                        except Exception as e:
                            print(str(e))
        self.settingSignal.emit(self.settingDict)  # 发射默认配置给主界面

        layout.addWidget(label('表格进度跟随鼠标'), 0, 0, 1, 1)
        self.tableRefreshCombox = QComboBox()
        self.tableRefreshCombox.addItems(['开启', '关闭'])
        self.tableRefreshCombox.setCurrentIndex(int(self.settingDict['tableRefresh']))
        self.tableRefreshCombox.currentIndexChanged.connect(self.changeSetting)
        layout.addWidget(self.tableRefreshCombox, 0, 1, 1, 1)

        layout.addWidget(label('限制表格刷新率'), 1, 0, 1, 1)
        self.tableRefreshFPSCombox = QComboBox()
        self.tableRefreshFPSCombox.addItems(['60FPS (有点吃配置)', '30FPS (推荐)', '20FPS', '10FPS'])
        self.tableRefreshFPSCombox.setCurrentIndex(int(self.settingDict['tableRefreshFPS']))
        self.tableRefreshFPSCombox.currentIndexChanged.connect(self.changeSetting)
        layout.addWidget(self.tableRefreshFPSCombox, 1, 1, 1, 1)

        layout.addWidget(label('限制波形图刷新率'), 2, 0, 1, 1)
        self.graphRefreshFPSCombox = QComboBox()
        self.graphRefreshFPSCombox.addItems(['60FPS (比较吃配置)', '30FPS (推荐)', '20FPS', '10FPS'])
        self.graphRefreshFPSCombox.setCurrentIndex(int(self.settingDict['graphRefreshFPS']))
        self.graphRefreshFPSCombox.currentIndexChanged.connect(self.changeSetting)
        layout.addWidget(self.graphRefreshFPSCombox, 2, 1, 1, 1)

    def changeSetting(self):
        self.settingDict['tableRefresh'] = self.tableRefreshCombox.currentIndex()
        self.settingDict['tableRefreshFPS'] = self.tableRefreshFPSCombox.currentIndex()
        self.settingDict['graphRefreshFPS'] = self.graphRefreshFPSCombox.currentIndex()
        try:
            with open('config', 'w') as cfg:  # 尝试更新配置文件
                for cfgName, cfgValue in self.settingDict.items():
                    cfg.write('%s=%s\n' % (cfgName, cfgValue))
        except Exception as e:
            print(str(e))
        self.settingSignal.emit(self.settingDict)  # 发射修改后的配置参数给主界面
Пример #2
0
class NameEditDialog(QDialog):
    sig_name_edit = Signal(str, int)

    def __init__(self):
        super().__init__()
        self.cmb_option = QComboBox(self)
        self.cmb_option.addItems(['접두', '접미'])
        self.cmb_option.setStyleSheet('font: 10pt \'맑은 고딕\'')
        self.cmb_option.setMinimumWidth(70)
        self.cmb_option.setMaximumWidth(100)
        self.line_text = NPLine()
        self.line_text.setStyleSheet('font: 10pt \'맑은 고딕\'')
        self.btn_ok = NPButton('실행', 10, self)
        self.btn_ok.clicked.connect(self.emit_sig_name_edit)

        box_h = QHBoxLayout()
        box_h.addWidget(self.line_text)
        box_h.addWidget(self.cmb_option)
        box_h.addWidget(self.btn_ok)
        box_h.setStretchFactor(self.cmb_option, 1)
        box_h.setStretchFactor(self.line_text, 4)
        box_h.setStretchFactor(self.btn_ok, 1)
        # box_h.setContentsMargins(3, 3, 3, 3)
        self.setLayout(box_h)
        self.setWindowTitle('선택한 이미지 파일 표제어 일괄 변경')
        self.setWindowIcon(QIcon('icon.png'))
        self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
        # self.resize(300, 40)

    def emit_sig_name_edit(self):
        self.sig_name_edit.emit(self.line_text.text(),
                                self.cmb_option.currentIndex())
Пример #3
0
class MyDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__()

        self.resize(400, 50)
        self.engine = 'dot'
        self.comboBox = QComboBox(self)
        self.engines = [('dot', 'for drawing directed graphs'),
                        ('neato', 'for drawing undirected graphs'),
                        ('twopi', 'for radial layouts of graphs'),
                        ('circo', 'for circular layout of graphs'),
                        ('fdp', 'for drawing undirected graphs'),
                        ('sfdp', 'for drawing large undirected graphs'),
                        ('patchwork', 'for squarified tree maps'),
                        ('osage', 'for array-based layouts')]
        for name, desc in self.engines:
            self.comboBox.addItem(name)

        self.comboBox.activated[str].connect(self.my_method)

    def my_method(self, engine_name):
        index = self.comboBox.currentIndex()
        self.setWindowTitle(self.engines[index][1])
        self.engine = engine_name
        print(self.engine)
class ThresholdingGui(QWidget):
    image: np.ndarray

    titles = ['Original Image', 'THRESH_BINARY + cv2.THRESH_OTSU']

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

        self.setWindowTitle('Otsu\'s Thresholding')

        open_image_btn = QPushButton('Open Image', self)
        open_image_btn.clicked.connect(self.open_image)

        self.method_combobox = QComboBox()
        for title in self.titles:
            self.method_combobox.addItem(title)
        self.method_combobox.currentIndexChanged.connect(self.update_preview)

        self.threshold_label = QLabel('Threshold calculated: -')

        self.image_label = QLabel()
        self.image = np.tile(
            np.arange(256, dtype=np.uint8).repeat(2), (512, 1))
        q_img = QImage(self.image.data, 512, 512, 512, QImage.Format_Indexed8)
        self.image_label.setPixmap(QPixmap.fromImage(q_img))

        # Create layout and add widgets
        layout = QVBoxLayout()
        layout.addWidget(open_image_btn)
        layout.addWidget(self.method_combobox)
        layout.addWidget(self.threshold_label)
        layout.addWidget(self.image_label)

        # Set dialog layout
        self.setLayout(layout)

    def open_image(self):
        image_path, _ = QFileDialog.getOpenFileName(
            self,
            "Load Image",
            filter="Image Files (*.tiff *.png *.jpeg *.jpg *.bmp)")
        if image_path:
            self.image = cv2.imread(image_path, 0)
            self.update_preview()

    def update_preview(self):
        method_idx = self.method_combobox.currentIndex()
        if method_idx == 0:
            ret, th = '-', self.image
        elif method_idx == 1:
            ret, th = cv2.threshold(self.image, 0, 255,
                                    cv2.THRESH_BINARY + cv2.THRESH_OTSU)

        self.threshold_label.setText(f"Threshold calculated: {ret}")

        image_h, image_w = th.shape
        q_img = QImage(th.data, image_w, image_h, image_w,
                       QImage.Format_Indexed8)
        self.image_label.setPixmap(QPixmap.fromImage(q_img))
Пример #5
0
 def setModelData(self, editor: QComboBox, model: QAbstractItemModel,
                  index: QModelIndex) -> None:
     selectedIndex: int = editor.currentIndex()
     mi = QPersistentModelIndex()
     if selectedIndex is not None and selectedIndex >= 0:
         mi = QPersistentModelIndex(
             self.__timeLabelModel.index(selectedIndex))
     model.setData(index, mi, Qt.EditRole)
Пример #6
0
class MyWindow(QWidget):
    def __init__(self):
        super().__init__()

        vbox1 = QVBoxLayout()
        self.my_lineedit = QLineEdit("What type of photo are you looking for?")
        self.my_lineedit.setMinimumWidth(250)
        self.my_lineedit.selectAll()
        self.my_btn = QPushButton("Submit")
        self.my_lbl = QLabel('')
        self.my_btn.clicked.connect(self.on_submit)
        self.my_lineedit.returnPressed.connect(self.on_submit)
        vbox1.addWidget(self.my_lineedit)
        vbox1.addWidget(self.my_btn)
        vbox1.addWidget(self.my_lbl)
        self.setLayout(vbox1)

        gbox1 = QGroupBox('Photo Search')
        gbox1.setLayout(vbox1)

        self.my_list = [
            "Pick a filter", 'None', 'Sepia', 'Negative', 'Grayscale',
            'Thumbnail'
        ]
        #                        0             1       2          3           4          5
        self.my_combo_box = QComboBox()
        self.my_combo_box.addItems(self.my_list)
        self.my_label = QLabel("")

        vbox2 = QVBoxLayout()
        vbox2.addWidget(self.my_combo_box)
        vbox2.addWidget(self.my_label)

        self.setLayout(vbox2)
        self.my_combo_box.currentIndexChanged.connect(self.update_ui)

        gbox2 = QGroupBox("Filters")
        gbox2.setLayout(vbox2)

        mbox = QVBoxLayout()
        mbox.addWidget(gbox1)
        mbox.addWidget(gbox2)

        self.setLayout(mbox)
        self.setWindowTitle("CST 205 App")

    @Slot()
    def on_submit(self):
        your_photo = self.my_lineedit.text()
        self.my_lbl.setText(f'Your photo is {your_photo}')

    @Slot()
    def update_ui(self):
        my_text = self.my_combo_box.currentText()
        my_index = self.my_combo_box.currentIndex()
        self.my_label.setText(f'You chose {self.my_list[my_index]}.')
Пример #7
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        centralWidget = QWidget()
        self.setCentralWidget(centralWidget)
        layout = QFormLayout(centralWidget)

        textLayout = QHBoxLayout()
        self.text = QLineEdit('Hello, PySide2')
        self.text.setClearButtonEnabled(True)
        textLayout.addWidget(self.text)
        self.sayButton = QPushButton('Say')
        textLayout.addWidget(self.sayButton)
        self.text.returnPressed.connect(self.sayButton.animateClick)
        self.sayButton.clicked.connect(self.say)
        layout.addRow('Text:', textLayout)

        self.voiceCombo = QComboBox()
        layout.addRow('Voice:', self.voiceCombo)

        self.volumeSlider = QSlider(Qt.Horizontal)
        self.volumeSlider.setMinimum(0)
        self.volumeSlider.setMaximum(100)
        self.volumeSlider.setValue(100)
        layout.addRow('Volume:', self.volumeSlider)

        self.engine = None
        engineNames = QTextToSpeech.availableEngines()
        if len(engineNames) > 0:
            engineName = engineNames[0]
            self.engine = QTextToSpeech(engineName)
            self.engine.stateChanged.connect(self.stateChanged)
            self.setWindowTitle(
                'QTextToSpeech Example ({})'.format(engineName))
            self.voices = []
            for voice in self.engine.availableVoices():
                self.voices.append(voice)
                self.voiceCombo.addItem(voice.name())
        else:
            self.setWindowTitle('QTextToSpeech Example (no engines available)')
            self.sayButton.setEnabled(False)

    def say(self):
        self.sayButton.setEnabled(False)
        self.engine.setVoice(self.voices[self.voiceCombo.currentIndex()])
        self.engine.setVolume(float(self.volumeSlider.value()) / 100)
        self.engine.say(self.text.text())

    def stateChanged(self, state):
        if (state == QTextToSpeech.State.Ready):
            self.sayButton.setEnabled(True)
Пример #8
0
class StateDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('State Editor')
        vbox = QVBoxLayout(self)
        layout = QGridLayout()
        self._line_name = QLineEdit()
        layout.addWidget(QLabel('Name'), 0, 0)
        layout.addWidget(self._line_name, 0, 1)

        self._combo_state_type = QComboBox()
        self._combo_state_type.addItems(["Normal", "Final", "Initial"])
        layout.addWidget(QLabel('Type'), 1, 0)
        layout.addWidget(self._combo_state_type, 1, 1)
        vbox.addLayout(layout)
        vbox.addWidget(QLabel('Comment'))

        self._comment = QTextEdit()
        vbox.addWidget(self._comment)

        hbox = QHBoxLayout()
        hbox.addStretch(1)
        btn_save = QPushButton('Save')
        hbox.addWidget(btn_save)
        btn_cancel = QPushButton('Cancel')
        hbox.addWidget(btn_cancel)
        vbox.addLayout(hbox)

        btn_save.clicked.connect(self.accept)
        btn_cancel.clicked.connect(self.reject)

    def get_name(self):
        return self._line_name.text().strip()

    def get_comment(self):
        return self._comment.toPlainText().strip()

    def get_state_type(self):
        states_map = {
            0: StateType.NORMAL,
            1: StateType.FINAL,
            2: StateType.INITIAL
        }
        return states_map.get(self._combo_state_type.currentIndex())
Пример #9
0
def _test_dropdown(dropdown: QComboBox,
                   level: Level,
                   level_attr: str,
                   expected_change,
                   index_change=+1):
    # WHEN the combobox has been changed using the header editor
    old_index = dropdown.currentIndex()
    old_attr_value = getattr(level, level_attr)

    new_index = old_index + index_change

    assert new_index > 0

    dropdown.setCurrentIndex(new_index)
    dropdown.activated.emit(new_index)

    new_attr_value = getattr(level, level_attr)

    # THEN the level attribute should have changed
    assert new_attr_value == old_attr_value + expected_change
Пример #10
0
class NewFileDialog(QDialog):
    def __init__(self):
        super(NewFileDialog, self).__init__()
        self.comboBox = QComboBox()
        self.comboBox.addItem("Assembly file")
        self.comboBox.addItem("C file")
        self.lineEdit = QLineEdit()
        self.lineEdit.setPlaceholderText("Enter file name...")
        self.setStyleSheet("background-color: #2D2D30; color: white;")
        self.setWindowIcon(QIcon(main.resource_path("resources/app_icon.ico")))
        self.hbox = QHBoxLayout()
        self.vbox = QVBoxLayout()
        self.create = QPushButton("Create")
        self.cancel = QPushButton("Cancel")
        self.setWindowTitle("New file")
        self.result = None
        self.initGUI()

    def initGUI(self):
        self.vbox.addWidget(self.lineEdit)
        self.vbox.addWidget(self.comboBox)
        self.hbox.addWidget(self.create)
        self.hbox.addWidget(self.cancel)
        self.create.setDefault(True)
        self.vbox.addLayout(self.hbox)
        self.setLayout(self.vbox)
        self.setFixedSize(self.sizeHint())

        self.create.clicked.connect(self.createButtonClicked)
        self.cancel.clicked.connect(self.cancelButtonClicked)

    def createButtonClicked(self):
        extension = ".S" if self.comboBox.currentIndex() == 0 else ".c"
        self.result = "{}{}".format(self.lineEdit.text().strip(), extension)
        self.close()

    def cancelButtonClicked(self):
        self.result = None
        self.close()
def saveAndCloseSettings(modeSelector: QtWidgets.QComboBox,
                         plainAppearance: QtWidgets.QCheckBox,
                         algorithmSelector: QtWidgets.QComboBox,
                         settingsWindow, levelSelector: QtWidgets.QComboBox,
                         create_subfolder: QtWidgets.QCheckBox, parent,
                         autoUpdate: QtWidgets.QCheckBox):
    global settings, forceClose
    if (algorithmSelector.currentIndex() == 0):
        settings['default_algorithm'] = "Deflated"
    elif (algorithmSelector.currentIndex() == 1):
        settings['default_algorithm'] = "BZIP2"
    elif (algorithmSelector.currentIndex() == 2):
        settings['default_algorithm'] = "LZMA"
    else:
        settings['default_algorithm'] = "Without Compression"

    settings["create_subdir"] = create_subfolder.isChecked()

    if (modeSelector.currentIndex() == 0):
        settings['mode'] = 'light'
    elif (modeSelector.currentIndex() == 1):
        settings['mode'] = 'dark'
    else:
        settings['mode'] = 'auto'

    settings["plainAppearance"] = plainAppearance.isChecked()

    settings["autoCheckForUpdates"] = autoUpdate.isChecked()

    parent.loadStyleSheet()

    settings["default_level"] = levelSelector.currentIndex() + 1

    forceClose = True
    settingsWindow.close()
    saveSettings(silent=True,
                 create_subdir=settings['create_subdir'],
                 default_level=settings['default_level'],
                 default_algorithm=settings['default_algorithm'],
                 mode=settings['mode'],
                 autoCheckForUpdates=settings["autoCheckForUpdates"])
Пример #12
0
class NGL_HKLViewer(QWidget):
    def __init__(self, parent=None):
        super(NGL_HKLViewer, self).__init__(parent)

        self.verbose = 0
        self.UseOSbrowser = False
        self.jscriptfname = ""
        self.devmode = False
        for e in sys.argv:
            if "verbose" in e:
                self.verbose = e.split("verbose=")[1]
            if "UseOSbrowser" in e:
                self.UseOSbrowser = e.split("UseOSbrowser=")[1]
            if "jscriptfname" in e:
                self.jscriptfname = e.split("jscriptfname=")[1]
            if "devmode" in e:
                self.devmode = True

        self.zmq_context = None
        self.bufsize = 20000

        self.originalPalette = QApplication.palette()

        self.openFileNameButton = QPushButton("Load reflection file")
        self.openFileNameButton.setDefault(True)
        self.openFileNameButton.clicked.connect(self.OpenReflectionsFile)

        self.debugbutton = QPushButton("Debug")
        self.debugbutton.clicked.connect(self.DebugInteractively)

        self.settingsbtn = QPushButton("Settings")
        self.settingsbtn.clicked.connect(self.SettingsDialog)

        self.mousemoveslider = QSlider(Qt.Horizontal)
        self.mousemoveslider.setMinimum(0)
        self.mousemoveslider.setMaximum(300)
        self.mousemoveslider.setValue(0)
        self.mousemoveslider.sliderReleased.connect(
            self.onFinalMouseSensitivity)
        self.mousemoveslider.valueChanged.connect(self.onMouseSensitivity)
        self.mousesensitxtbox = QLineEdit('')
        self.mousesensitxtbox.setReadOnly(True)
        self.fontspinBox = QDoubleSpinBox()
        self.fontspinBox.setSingleStep(1)
        self.fontspinBox.setRange(4, 50)
        self.font = QFont()
        self.font.setFamily(self.font.defaultFamily())
        self.fontspinBox.setValue(self.font.pointSize())
        #self.fontspinBox.setValue(self.font.pixelSize())
        self.fontspinBox.valueChanged.connect(self.onFontsizeChanged)
        self.Fontsize_labeltxt = QLabel()
        self.Fontsize_labeltxt.setText("Font size:")

        self.cameraPerspectCheckBox = QCheckBox()
        self.cameraPerspectCheckBox.setText("Perspective camera")
        self.cameraPerspectCheckBox.clicked.connect(self.onCameraPerspect)
        self.cameraPerspectCheckBox.setCheckState(Qt.Unchecked)

        self.settingsform = SettingsForm(self)

        self.MillerComboBox = QComboBox()
        self.MillerComboBox.activated.connect(self.onMillerComboSelchange)
        #self.MillerComboBox.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.MillerLabel = QLabel()
        self.MillerLabel.setText("Selected HKL Scene")

        self.HKLnameedit = QLineEdit('')
        self.HKLnameedit.setReadOnly(True)
        self.textInfo = QTextEdit()
        self.textInfo.setLineWrapMode(QTextEdit.NoWrap)
        self.textInfo.setReadOnly(True)

        labels = [
            "Label", "Type", "no. of HKLs", "Span of HKLs", "Min Max data",
            "Min Max sigmas", "d_min, d_max", "Symmetry unique", "Anomalous"
        ]
        self.millertable = QTableWidget(0, len(labels))
        self.millertable.setHorizontalHeaderLabels(labels)
        self.millertable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        # don't allow editing this table
        self.millertable.setEditTriggers(QTableWidget.NoEditTriggers)

        self.createExpansionBox()
        self.createFileInfoBox()
        self.CreateSliceTabs()
        self.createRadiiScaleGroupBox()
        self.createBinsBox()
        self.CreateFunctionTabs()

        mainLayout = QGridLayout()
        mainLayout.addWidget(self.FileInfoBox, 0, 0)
        mainLayout.addWidget(self.MillerLabel, 1, 0)
        mainLayout.addWidget(self.MillerComboBox, 2, 0)
        mainLayout.addWidget(self.functionTabWidget, 3, 0)
        mainLayout.addWidget(self.settingsbtn, 4, 0, 1, 1)

        #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) )
        if self.UseOSbrowser == False:
            self.BrowserBox = QWebEngineView()
            mainLayout.addWidget(self.BrowserBox, 0, 1, 5, 3)
            self.BrowserBox.setUrl("https://cctbx.github.io/")
            #self.BrowserBox.setUrl("https://webglreport.com/")
            #self.BrowserBox.loadFinished.connect(self.onLoadFinished)
            mainLayout.setColumnStretch(2, 1)

        mainLayout.setRowStretch(0, 1)
        mainLayout.setRowStretch(1, 0)
        mainLayout.setRowStretch(2, 1)
        mainLayout.setRowStretch(3, 1)
        mainLayout.setColumnStretch(4, 0)
        self.setLayout(mainLayout)

        self.setWindowTitle("HKL-Viewer")
        self.cctbxproc = None
        self.LaunchCCTBXPython()
        self.out = None
        self.err = None
        self.comboviewwidth = 0
        self.hklscenes_arrays = []
        self.array_infotpls = []
        self.matching_arrays = []
        self.bin_infotpls = None
        self.bin_opacities = None
        self.html_url = ""
        self.spacegroups = []
        self.info = []
        self.infostr = ""
        self.fileisvalid = False
        self.NewFileLoaded = False
        self.NewHKLscenes = False
        self.updatingNbins = False
        self.binstableitemchanges = False

        self.show()

    def SettingsDialog(self):
        self.settingsform.show()

    def update(self):
        if self.cctbxproc:
            if self.cctbxproc.stdout:
                print(self.cctbxproc.stdout.read().decode("utf-8"))
            if self.cctbxproc.stderr:
                print(self.cctbxproc.stderr.read().decode("utf-8"))
        if self.out:
            print(self.out.decode("utf-8"))
        if self.err:
            print(self.err.decode("utf-8"))
        if self.zmq_context:
            try:
                msg = self.socket.recv(
                    flags=zmq.NOBLOCK
                )  #To empty the socket from previous messages
                msgstr = msg.decode()
                self.infodict = eval(msgstr)
                #print("received from cctbx: " + str(self.infodict))
                if self.infodict:

                    if self.infodict.get("hklscenes_arrays"):
                        self.hklscenes_arrays = self.infodict.get(
                            "hklscenes_arrays", [])

                    if self.infodict.get("array_infotpls"):
                        self.array_infotpls = self.infodict.get(
                            "array_infotpls", [])

                    if self.infodict.get("bin_data_label"):
                        self.BinDataComboBox.setCurrentText(
                            self.infodict["bin_data_label"])

                    if self.infodict.get("bin_infotpls"):
                        self.bin_infotpls = self.infodict["bin_infotpls"]

                        self.nbins = len(self.bin_infotpls)
                        self.updatingNbins = True
                        self.Nbins_spinBox.setValue(self.nbins)
                        self.updatingNbins = False
                        self.binstable.clearContents()
                        self.binstable.setRowCount(self.nbins)
                        for row, bin_infotpl in enumerate(self.bin_infotpls):
                            for col, elm in enumerate(bin_infotpl):
                                # only allow changing the last column with opacity values
                                if col != 3:
                                    item = QTableWidgetItem(str(elm))
                                else:
                                    item = QTableWidgetItem()
                                    item.setFlags(Qt.ItemIsUserCheckable
                                                  | Qt.ItemIsEnabled)
                                    item.setCheckState(Qt.Checked)
                                item.setFlags(item.flags() ^ Qt.ItemIsEditable)
                                self.binstable.setItem(row, col, item)
                        if self.bin_opacities:
                            self.update_table_opacities()

                    if self.infodict.get("bin_opacities"):
                        self.bin_opacities = self.infodict["bin_opacities"]
                        if self.binstable.rowCount() > 0:
                            self.update_table_opacities()

                    if self.infodict.get("html_url"):
                        self.html_url = self.infodict["html_url"]
                        if self.UseOSbrowser == False:
                            self.BrowserBox.setUrl(self.html_url)
                            # workaround for background colour bug in chromium
                            # https://bugreports.qt.io/browse/QTBUG-41960
                            self.BrowserBox.page().setBackgroundColor(
                                QColor(100, 100, 100, 1.0))

                    if self.infodict.get("spacegroups"):
                        self.spacegroups = self.infodict.get("spacegroups", [])
                        self.SpaceGroupComboBox.clear()
                        self.SpaceGroupComboBox.addItems(self.spacegroups)

                    if self.infodict.get("merge_data"):
                        self.mergedata = self.infodict["merge_data"]

                    currentinfostr = ""
                    if self.infodict.get("info"):
                        currentinfostr = self.infodict.get("info", [])

                    if self.infodict.get("NewFileLoaded"):
                        self.NewFileLoaded = self.infodict.get(
                            "NewFileLoaded", False)

                    if self.infodict.get("NewHKLscenes"):
                        self.NewHKLscenes = self.infodict.get(
                            "NewHKLscenes", False)

                    self.fileisvalid = True
                    #print("ngl_hkl_infodict: " + str(ngl_hkl_infodict))

                    if currentinfostr:
                        #print(currentinfostr)
                        self.infostr += currentinfostr + "\n"
                        # display no more than self.bufsize bytes of text
                        self.infostr = self.infostr[-self.bufsize:]
                        self.textInfo.setPlainText(self.infostr)
                        self.textInfo.verticalScrollBar().setValue(
                            self.textInfo.verticalScrollBar().maximum())

                    if self.NewFileLoaded and self.NewHKLscenes:
                        #if self.mergedata == True : val = Qt.CheckState.Checked
                        #if self.mergedata == None : val = Qt.CheckState.PartiallyChecked
                        #if self.mergedata == False : val = Qt.CheckState.Unchecked
                        #self.mergecheckbox.setCheckState(val )
                        #print("got hklscenes: " + str(self.hklscenes_arrays))

                        self.MillerComboBox.clear()
                        self.MillerComboBox.addItems(
                            [e[3] for e in self.hklscenes_arrays])
                        self.MillerComboBox.setCurrentIndex(
                            -1)  # unselect the first item in the list
                        self.comboviewwidth = 0
                        for e in self.hklscenes_arrays:
                            self.comboviewwidth = max(
                                self.comboviewwidth,
                                self.MillerComboBox.fontMetrics().width(e[3]))
                        self.MillerComboBox.view().setMinimumWidth(
                            self.comboviewwidth)

                        self.millertable.clearContents()
                        self.millertable.setRowCount(len(
                            self.hklscenes_arrays))
                        for n, millarr in enumerate(self.array_infotpls):
                            for m, elm in enumerate(millarr):
                                self.millertable.setItem(
                                    n, m, QTableWidgetItem(str(elm)))
                        self.functionTabWidget.setDisabled(True)
                        self.NewFileLoaded = False

                    if self.NewHKLscenes:
                        self.BinDataComboBox.clear()
                        self.BinDataComboBox.addItems(
                            ["Resolution"] +
                            [e[3] for e in self.hklscenes_arrays])
                        self.BinDataComboBox.view().setMinimumWidth(
                            self.comboviewwidth)
                        #self.BinDataComboBox.setCurrentIndex(-1) # unselect the first item in the list
                        self.NewHKLscenes = False

            except Exception as e:
                errmsg = str(e)
                if "Resource temporarily unavailable" not in errmsg:
                    print(errmsg + traceback.format_exc(limit=10))
                pass

    def onFinalMouseSensitivity(self):
        val = self.mousemoveslider.value() / 100.0
        self.NGL_HKL_command(
            'NGL_HKLviewer.viewer.NGL.mouse_sensitivity = %f' % val)

    def onMouseSensitivity(self):
        val = self.mousemoveslider.value() / 100.0
        self.mousesensitxtbox.setText("%2.2f" % val)

    def onFontsizeChanged(self, val):
        font = app.font()
        font.setPointSize(val)
        app.setFont(font)
        self.settingsform.setFixedSize(self.settingsform.sizeHint())

    def onCameraPerspect(self, val):
        if self.cameraPerspectCheckBox.isChecked():
            self.NGL_HKL_command("NGL_HKLviewer.camera_type = perspective")
        else:
            self.NGL_HKL_command("NGL_HKLviewer.camera_type = orthographic")

    def MergeData(self):
        if self.mergecheckbox.checkState() == Qt.CheckState.Checked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = True')
        if self.mergecheckbox.checkState() == Qt.CheckState.PartiallyChecked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = None')
        if self.mergecheckbox.checkState() == Qt.CheckState.Unchecked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = False')

    def ExpandToP1(self):
        if self.expandP1checkbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = True')
        else:
            self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = False')

    def ExpandAnomalous(self):
        if self.expandAnomalouscheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.expand_anomalous = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.expand_anomalous = False')

    def showSysAbsent(self):
        if self.sysabsentcheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_systematic_absences = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_systematic_absences = False')

    def showMissing(self):
        if self.missingcheckbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = True')
        else:
            self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = False')

    def showOnlyMissing(self):
        if self.onlymissingcheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_only_missing = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_only_missing = False')

    def showSlice(self):
        if self.showslicecheckbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.slice_mode = True')
            if self.expandP1checkbox.isChecked():
                self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                       expand_to_p1 = True
                                                       inbrowser = False
                                                    }
                             """)
            if self.expandAnomalouscheckbox.isChecked():
                self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                       expand_anomalous = True
                                                       inbrowser = False
                                                     }
                             """)
        else:
            self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                      slice_mode = False
                                                      inbrowser = True
                                                    }
                            """)

    def onSliceComboSelchange(self, i):
        rmin = self.array_infotpls[self.MillerComboBox.currentIndex()][3][0][i]
        rmax = self.array_infotpls[self.MillerComboBox.currentIndex()][3][1][i]
        self.sliceindexspinBox.setRange(rmin, rmax)
        self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_axis = %s" %
                             self.sliceaxis[i])

    def onSliceIndexChanged(self, val):
        self.sliceindex = val
        self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_index = %d" %
                             self.sliceindex)

    def onBindataComboSelchange(self, i):
        if self.BinDataComboBox.currentText():
            if self.BinDataComboBox.currentIndex() > 0:
                bin_scene_label = str(self.BinDataComboBox.currentIndex() - 1)
            else:
                bin_scene_label = "Resolution"
            self.NGL_HKL_command("NGL_HKLviewer.bin_scene_label = %s" %
                                 bin_scene_label)

    def update_table_opacities(self, allalpha=None):
        bin_opacitieslst = eval(self.bin_opacities)
        self.binstable_isready = False
        for binopacity in bin_opacitieslst:
            if not allalpha:
                alpha = float(binopacity.split(",")[0])
            else:
                alpha = allalpha
            bin = int(binopacity.split(",")[1])
            item = QTableWidgetItem()
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            if alpha < 0.5:
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)
            item.setFlags(item.flags() ^ Qt.ItemIsEditable)
            self.binstable.setItem(bin, 3, item)
        self.binstable_isready = True

    def SetOpaqueAll(self):
        if self.binstableitemchanges:
            return
        bin_opacitieslst = eval(self.bin_opacities)
        nbins = len(bin_opacitieslst)
        sum = 0
        for binopacity in bin_opacitieslst:
            sum += float(binopacity.split(",")[0])
        if sum >= nbins:
            self.OpaqueAllCheckbox.setCheckState(Qt.Checked)
        if sum == 0:
            self.OpaqueAllCheckbox.setCheckState(Qt.Unchecked)
        if sum > 0.0 and sum < nbins:
            self.OpaqueAllCheckbox.setCheckState(Qt.PartiallyChecked)

    def onBinsTableItemChanged(self, item):
        row = item.row()
        column = item.column()
        try:
            if item.checkState() == Qt.Unchecked:
                newval = 0
            else:
                newval = 1.0
            if column == 3 and self.binstable_isready:  # changing opacity
                assert (newval <= 1.0 and newval >= 0.0)
                bin_opacitieslst = eval(self.bin_opacities)
                bin_opacitieslst[row] = str(newval) + ', ' + str(row)
                self.bin_opacities = str(bin_opacitieslst)
                self.SetOpaqueAll()
                self.NGL_HKL_command(
                    'NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' %
                    self.bin_opacities)
        except Exception as e:
            print(str(e))
            #self.binstable.currentItem().setText( self.currentSelectedBinsTableVal)

    def onBinsTableItemSelectionChanged(self):
        row = self.binstable.currentItem().row()
        column = self.binstable.currentItem().column()
        self.currentSelectedBinsTableVal = self.binstable.currentItem().text()
        #print( "in itemSelectionChanged " + self.currentSelectedBinsTableVal)

    def onOpaqueAll(self):
        self.binstableitemchanges = True
        bin_opacitieslst = eval(self.bin_opacities)
        nbins = len(bin_opacitieslst)
        bin_opacitieslst = []
        self.binstable_isready = False
        if self.OpaqueAllCheckbox.isChecked():
            for i in range(nbins):
                bin_opacitieslst.append("1.0, %d" % i)
        else:
            for i in range(nbins):
                bin_opacitieslst.append("0.0, %d" % i)
        self.bin_opacities = str(bin_opacitieslst)
        self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' %
                             self.bin_opacities)
        self.binstableitemchanges = False
        self.binstable_isready = True

    """
  def onLoadFinished(self, val):
    pass
    #print("web page finished loading now")


  def onBinsTableitemActivated(self, item):
    row = item.row()
    column = item.column()
    currentval = item.text()
    #print( "in itemActivated " + currentval)


  def onBinsTableCellentered(self, row, col):
    pass
    #print( "in Cellentered " + self.binstable.currentItem().text() )


  def onBinsTableCellPressed(self, row, col):
    pass
    #print( "in CellPressed " + self.binstable.currentItem().text() )
  """

    def onNbinsChanged(self, val):
        self.nbins = val
        if not self.updatingNbins:  # avoid possible endless loop to cctbx
            self.NGL_HKL_command("NGL_HKLviewer.nbins = %d" % self.nbins)

    def onRadiiScaleChanged(self, val):
        self.radii_scale = val
        self.NGL_HKL_command("""
      NGL_HKLviewer.viewer {
        nth_power_scale_radii = %f
        scale = %f
      }
      """ % (self.nth_power_scale, self.radii_scale))

    def onPowerScaleChanged(self, val):
        self.nth_power_scale = val
        self.NGL_HKL_command("""
      NGL_HKLviewer.viewer {
        nth_power_scale_radii = %f
        scale = %f
      }
      """ % (self.nth_power_scale, self.radii_scale))

    def onManualPowerScale(self):
        if self.ManualPowerScalecheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.nth_power_scale_radii = %f' %
                self.nth_power_scale)
            self.power_scale_spinBox.setEnabled(True)
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.nth_power_scale_radii = -1.0')
            self.power_scale_spinBox.setEnabled(False)
            self.nth_power_scale = -1.0

    def OpenReflectionsFile(self):
        options = QFileDialog.Options()
        fileName, filtr = QFileDialog.getOpenFileName(
            self, "Load reflections file", "",
            "All Files (*);;MTZ Files (*.mtz);;CIF (*.cif)", "", options)
        if fileName:
            self.HKLnameedit.setText(fileName)
            #self.infostr = ""
            self.textInfo.setPlainText("")
            self.fileisvalid = False
            self.NGL_HKL_command('NGL_HKLviewer.filename = "%s"' % fileName)
            self.MillerComboBox.clear()
            self.BinDataComboBox.clear()

    def createExpansionBox(self):
        self.SpaceGroupComboBox = QComboBox()
        self.SpaceGroupComboBox.activated.connect(self.SpacegroupSelchange)

        self.SpacegroupLabel = QLabel()
        self.SpacegroupLabel.setText("Space Subgroups")

        self.mergecheckbox = QCheckBox()
        self.mergecheckbox.setText("Merge data")
        #self.mergecheckbox.setTristate (True)
        self.mergecheckbox.clicked.connect(self.MergeData)

        self.expandP1checkbox = QCheckBox()
        self.expandP1checkbox.setText("Expand to P1")
        self.expandP1checkbox.clicked.connect(self.ExpandToP1)

        self.expandAnomalouscheckbox = QCheckBox()
        self.expandAnomalouscheckbox.setText("Show Friedel pairs")
        self.expandAnomalouscheckbox.clicked.connect(self.ExpandAnomalous)

        self.sysabsentcheckbox = QCheckBox()
        self.sysabsentcheckbox.setText("Show Systematic Absences")
        self.sysabsentcheckbox.clicked.connect(self.showSysAbsent)

        self.missingcheckbox = QCheckBox()
        self.missingcheckbox.setText("Show Missing")
        self.missingcheckbox.clicked.connect(self.showMissing)

        self.onlymissingcheckbox = QCheckBox()
        self.onlymissingcheckbox.setText("Only Show Missing")
        self.onlymissingcheckbox.clicked.connect(self.showOnlyMissing)

        self.ExpansionBox = QGroupBox("Expansions")
        layout = QGridLayout()
        layout.addWidget(self.SpacegroupLabel, 0, 0)
        layout.addWidget(self.SpaceGroupComboBox, 0, 1)
        #layout.addWidget(self.mergecheckbox,             1, 0)
        layout.addWidget(self.expandP1checkbox, 1, 0)
        layout.addWidget(self.expandAnomalouscheckbox, 1, 1)
        layout.addWidget(self.sysabsentcheckbox, 2, 0)
        layout.addWidget(self.missingcheckbox, 3, 0)
        layout.addWidget(self.onlymissingcheckbox, 3, 1)
        layout.setRowStretch(0, 0)
        layout.setRowStretch(1, 0)
        layout.setRowStretch(2, 0)
        layout.setRowStretch(3, 1)
        self.ExpansionBox.setLayout(layout)

    def CreateSliceTabs(self):
        self.showslicecheckbox = QCheckBox()
        self.showslicecheckbox.setText("Show Slice")
        self.showslicecheckbox.clicked.connect(self.showSlice)

        self.sliceindexspinBox = QDoubleSpinBox()
        self.sliceindex = 0
        self.sliceindexspinBox.setValue(self.sliceindex)
        self.sliceindexspinBox.setDecimals(0)
        self.sliceindexspinBox.setSingleStep(1)
        self.sliceindexspinBox.setRange(0, 20)
        self.sliceindexspinBox.valueChanged.connect(self.onSliceIndexChanged)

        self.SliceLabelComboBox = QComboBox()
        self.SliceLabelComboBox.activated.connect(self.onSliceComboSelchange)
        self.sliceaxis = ["h", "k", "l"]
        self.SliceLabelComboBox.addItems(self.sliceaxis)

        self.sliceTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.showslicecheckbox, 0, 0, 1, 1)
        layout1.addWidget(self.SliceLabelComboBox, 0, 1, 1, 1)
        layout1.addWidget(self.sliceindexspinBox, 0, 2, 1, 1)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.hvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hvecval = 2.0
        self.hvec_spinBox.setValue(self.hvecval)
        self.hvec_spinBox.setDecimals(2)
        self.hvec_spinBox.setSingleStep(0.5)
        self.hvec_spinBox.setRange(-100.0, 10.0)
        self.hvec_spinBox.valueChanged.connect(self.onHvecChanged)
        self.hvec_Label = QLabel()
        self.hvec_Label.setText("H")
        layout2.addWidget(self.hvec_Label, 0, 0, 1, 1)
        layout2.addWidget(self.hvec_spinBox, 0, 1, 1, 1)

        self.kvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.kvecval = 0.0
        self.kvec_spinBox.setValue(self.kvecval)
        self.kvec_spinBox.setDecimals(2)
        self.kvec_spinBox.setSingleStep(0.5)
        self.kvec_spinBox.setRange(-100.0, 100.0)
        self.kvec_spinBox.valueChanged.connect(self.onKvecChanged)
        self.kvec_Label = QLabel()
        self.kvec_Label.setText("K")
        layout2.addWidget(self.kvec_Label, 1, 0, 1, 1)
        layout2.addWidget(self.kvec_spinBox, 1, 1, 1, 1)

        self.lvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.lvecval = 0.0
        self.lvec_spinBox.setValue(self.lvecval)
        self.lvec_spinBox.setDecimals(2)
        self.lvec_spinBox.setSingleStep(0.5)
        self.lvec_spinBox.setRange(-100.0, 100.0)
        self.lvec_spinBox.valueChanged.connect(self.onLvecChanged)
        self.lvec_Label = QLabel()
        self.lvec_Label.setText("L")
        layout2.addWidget(self.lvec_Label, 2, 0, 1, 1)
        layout2.addWidget(self.lvec_spinBox, 2, 1, 1, 1)

        self.hkldist_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hkldistval = 0.0
        self.hkldist_spinBox.setValue(self.hkldistval)
        self.hkldist_spinBox.setDecimals(2)
        self.hkldist_spinBox.setSingleStep(0.5)
        self.hkldist_spinBox.setRange(-100.0, 100.0)
        self.hkldist_spinBox.valueChanged.connect(self.onHKLdistChanged)
        self.hkldist_Label = QLabel()
        self.hkldist_Label.setText("Distance from Origin")
        layout2.addWidget(self.hkldist_Label, 3, 0, 1, 1)
        layout2.addWidget(self.hkldist_spinBox, 3, 1, 1, 1)

        self.clipwidth_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.clipwidthval = 0.5
        self.clipwidth_spinBox.setValue(self.clipwidthval)
        self.clipwidth_spinBox.setDecimals(2)
        self.clipwidth_spinBox.setSingleStep(0.05)
        self.clipwidth_spinBox.setRange(0.0, 100.0)
        self.clipwidth_spinBox.valueChanged.connect(self.onClipwidthChanged)
        self.clipwidth_Label = QLabel()
        self.clipwidth_Label.setText("Clip Plane Width")
        layout2.addWidget(self.clipwidth_Label, 4, 0, 1, 1)
        layout2.addWidget(self.clipwidth_spinBox, 4, 1, 1, 1)

        self.ClipBox = QGroupBox("Normal Vector to Clip Plane")
        self.ClipBox.setLayout(layout2)

        layout3 = QGridLayout()
        self.ClipPlaneChkBox = QCheckBox(self.sliceTabWidget)
        self.ClipPlaneChkBox.setText(
            "Use clip plane normal to HKL vector pointing out")
        self.ClipPlaneChkBox.clicked.connect(self.onClipPlaneChkBox)

        layout3.addWidget(self.ClipPlaneChkBox, 0, 0)
        layout3.addWidget(self.ClipBox, 1, 0)
        tab2.setLayout(layout3)
        self.sliceTabWidget.addTab(tab1, "Explicit Slicing")
        self.sliceTabWidget.addTab(tab2, "Clip Plane Slicing")
        self.ClipBox.setDisabled(True)

    def onClipPlaneChkBox(self):
        if self.ClipPlaneChkBox.isChecked():
            self.ClipBox.setDisabled(False)
            philstr = """NGL_HKLviewer.normal_clip_plane {
  h = %s
  k = %s
  l = %s
  hkldist = %s
  clipwidth = %s
}
  NGL_HKLviewer.viewer.NGL.fixorientation = %s

      """ %(self.hvecval, self.kvecval, self.lvecval, self.hkldistval, self.clipwidthval, \
                                    str(self.fixedorientcheckbox.isChecked()) )
            self.NGL_HKL_command(philstr)
        else:
            self.ClipBox.setDisabled(True)
            self.NGL_HKL_command(
                "NGL_HKLviewer.normal_clip_plane.clipwidth = None")

    def onClipwidthChanged(self, val):
        self.clipwidthval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.clipwidth = %f" %
                             self.clipwidthval)

    def onHKLdistChanged(self, val):
        self.hkldistval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.hkldist = %f" %
                             self.hkldistval)

    def onHvecChanged(self, val):
        self.hvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.h = %f" %
                             self.hvecval)

    def onKvecChanged(self, val):
        self.kvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.k = %f" %
                             self.kvecval)

    def onLvecChanged(self, val):
        self.lvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.l = %f" %
                             self.lvecval)

    def onFixedorient(self):
        self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.fixorientation = %s' \
                                        %str(self.fixedorientcheckbox.isChecked()))

    def onMillerComboSelchange(self, i):
        self.NGL_HKL_command("NGL_HKLviewer.scene_id = %d" % i)
        #self.MillerComboBox.setCurrentIndex(i)
        if self.MillerComboBox.currentText():
            self.functionTabWidget.setEnabled(True)
            self.expandAnomalouscheckbox.setEnabled(True)
            # don' allow anomalous expansion for data that's already anomalous
            for arrayinfo in self.array_infotpls:
                isanomalous = arrayinfo[-1]
                label = arrayinfo[0]
                if isanomalous and label == self.MillerComboBox.currentText(
                )[:len(label)]:
                    self.expandAnomalouscheckbox.setDisabled(True)
        else:
            self.functionTabWidget.setDisabled(True)

        self.SpaceGroupComboBox.clear()
        self.SpaceGroupComboBox.addItems(self.spacegroups)
        # need to supply issymunique flag in infotuple
        #if self.hklscenes_arrays[ i ][6] == 0:
        #  self.mergecheckbox.setEnabled(True)
        #else:
        #  self.mergecheckbox.setEnabled(False)

    def createFileInfoBox(self):
        self.FileInfoBox = QGroupBox("Reflection File Information")
        layout = QGridLayout()
        layout.addWidget(self.openFileNameButton, 0, 0, 1, 2)
        if self.devmode:
            layout.addWidget(self.debugbutton, 0, 2, 1, 1)
        layout.addWidget(self.HKLnameedit, 1, 0, 1, 3)
        layout.addWidget(self.millertable, 2, 0, 1, 3)
        layout.addWidget(self.textInfo, 3, 0, 1, 3)
        #layout.setColumnStretch(1, 2)
        self.FileInfoBox.setLayout(layout)

    def createRadiiScaleGroupBox(self):
        self.RadiiScaleGroupBox = QGroupBox("Radii Size of HKL Spheres")

        self.ManualPowerScalecheckbox = QCheckBox()
        self.ManualPowerScalecheckbox.setText(
            "Manual Power Scaling of Sphere Radii")
        self.ManualPowerScalecheckbox.clicked.connect(self.onManualPowerScale)

        self.power_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox)
        self.nth_power_scale = 0.5
        self.power_scale_spinBox.setValue(self.nth_power_scale)
        self.power_scale_spinBox.setDecimals(2)
        self.power_scale_spinBox.setSingleStep(0.05)
        self.power_scale_spinBox.setRange(0.0, 1.0)
        self.power_scale_spinBox.valueChanged.connect(self.onPowerScaleChanged)
        self.power_scale_spinBox.setEnabled(False)
        self.powerscaleLabel = QLabel()
        self.powerscaleLabel.setText("Power scale Factor")

        self.radii_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox)
        self.radii_scale = 1.0
        self.radii_scale_spinBox.setValue(self.radii_scale)
        self.radii_scale_spinBox.setDecimals(1)
        self.radii_scale_spinBox.setSingleStep(0.1)
        self.radii_scale_spinBox.setRange(0.2, 2.0)
        self.radii_scale_spinBox.valueChanged.connect(self.onRadiiScaleChanged)
        self.radiiscaleLabel = QLabel()
        self.radiiscaleLabel.setText("Linear Scale Factor")

        layout = QGridLayout()
        layout.addWidget(self.ManualPowerScalecheckbox, 1, 0, 1, 2)
        layout.addWidget(self.powerscaleLabel, 2, 0, 1, 2)
        layout.addWidget(self.power_scale_spinBox, 2, 1, 1, 2)
        layout.addWidget(self.radiiscaleLabel, 3, 0, 1, 2)
        layout.addWidget(self.radii_scale_spinBox, 3, 1, 1, 2)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 0)
        self.RadiiScaleGroupBox.setLayout(layout)

    def createBinsBox(self):
        self.binstable = QTableWidget(0, 4)
        self.binstable_isready = False
        labels = [
            "no. of HKLs", "lower bin value", "upper bin value", "opacity"
        ]
        self.binstable.setHorizontalHeaderLabels(labels)
        self.binstable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        self.bindata_labeltxt = QLabel()
        self.bindata_labeltxt.setText("Data binned:")
        self.Nbins_spinBox = QSpinBox()
        self.Nbins_spinBox.setSingleStep(1)
        self.Nbins_spinBox.setRange(1, 40)
        self.Nbins_spinBox.valueChanged.connect(self.onNbinsChanged)
        self.Nbins_labeltxt = QLabel()
        self.Nbins_labeltxt.setText("Number of bins:")

        self.OpaqueAllCheckbox = QCheckBox()
        #self.OpaqueAllCheckbox.setTristate()
        self.OpaqueAllCheckbox.setText("Show all data in bins")
        self.OpaqueAllCheckbox.clicked.connect(self.onOpaqueAll)

        self.binstable.itemChanged.connect(self.onBinsTableItemChanged)
        self.binstable.itemSelectionChanged.connect(
            self.onBinsTableItemSelectionChanged)
        self.BinDataComboBox = QComboBox()
        self.BinDataComboBox.activated.connect(self.onBindataComboSelchange)
        self.BinsGroupBox = QGroupBox("Bins")
        layout = QGridLayout()
        layout.addWidget(self.bindata_labeltxt, 0, 0)
        layout.addWidget(self.BinDataComboBox, 0, 1)
        layout.addWidget(self.Nbins_labeltxt, 0, 2)
        layout.addWidget(self.Nbins_spinBox, 0, 3)
        layout.addWidget(self.OpaqueAllCheckbox, 1, 2)
        layout.addWidget(self.binstable, 2, 0, 1, 4)
        layout.setColumnStretch(0, 0)
        layout.setColumnStretch(1, 2)
        layout.setColumnStretch(3, 1)
        self.BinsGroupBox.setLayout(layout)

    def DebugInteractively(self):
        import code, traceback
        code.interact(local=locals(),
                      banner="".join(traceback.format_stack(limit=10)))

    def CreateFunctionTabs(self):
        self.functionTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.ExpansionBox, 0, 0)
        layout1.setRowStretch(0, 0)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.fixedorientcheckbox = QCheckBox(self.sliceTabWidget)
        self.fixedorientcheckbox.setText(
            "Fix orientation but allow zoom and translation")
        self.fixedorientcheckbox.clicked.connect(self.onFixedorient)
        layout2.addWidget(self.fixedorientcheckbox, 0, 0)

        layout2.addWidget(self.sliceTabWidget, 1, 0)
        tab2.setLayout(layout2)

        tab3 = QWidget()
        layout3 = QGridLayout()
        layout3.addWidget(self.RadiiScaleGroupBox, 0, 0)
        tab3.setLayout(layout3)

        tab4 = QWidget()
        layout4 = QGridLayout()
        layout4.addWidget(self.BinsGroupBox, 0, 0)
        tab4.setLayout(layout4)

        self.functionTabWidget.addTab(tab1, "Expand")
        self.functionTabWidget.addTab(tab2, "Slice")
        self.functionTabWidget.addTab(tab3, "Size")
        self.functionTabWidget.addTab(tab4, "Bins")
        self.functionTabWidget.setDisabled(True)

    def SpacegroupSelchange(self, i):
        self.NGL_HKL_command("NGL_HKLviewer.spacegroup_choice = %d" % i)

    def find_free_port(self):
        import socket
        s = socket.socket()
        s.bind(('', 0))  # Bind to a free port provided by the host.
        port = s.getsockname()[1]
        s.close()
        return port

    def LaunchCCTBXPython(self):
        self.sockport = self.find_free_port()
        self.zmq_context = zmq.Context()
        self.socket = self.zmq_context.socket(zmq.PAIR)
        self.socket.bind("tcp://127.0.0.1:%s" % self.sockport)
        try:
            msg = self.socket.recv(
                flags=zmq.NOBLOCK)  #To empty the socket from previous messages
        except Exception as e:
            pass
        cmdargs = 'cctbx.python.bat -i -c "from crys3d.hklview import cmdlineframes;' \
         + ' myHKLview = cmdlineframes.HKLViewFrame(useGuiSocket=%s, high_quality=True,' %self.sockport \
         + ' jscriptfname = \'%s\', ' %self.jscriptfname \
         + ' verbose=%s, UseOSBrowser= %s )"\n' %(self.verbose, str(self.UseOSbrowser))
        self.cctbxproc = subprocess.Popen(cmdargs,
                                          shell=True,
                                          stdin=subprocess.PIPE,
                                          stdout=sys.stdout,
                                          stderr=sys.stderr)
        #time.sleep(1)

    def NGL_HKL_command(self, cmdstr):
        #print("sending:\n" + cmdstr)
        self.socket.send(bytes(cmdstr, "utf-8"))
Пример #13
0
class DeepGraphs(cutter.CutterDockWidget):
    def __init__(self, parent, action):
        super(DeepGraphs, self).__init__(parent, action)
        self.setObjectName("DeepGraphs")
        self.setWindowTitle("Deep graphs")

        content = QWidget()
        self.setWidget(content)

        # Create layout
        layout = QVBoxLayout(content)
        content.setLayout(layout)

        self.output_path = QLineEdit(content)
        self.output_path.setText("PATH")
        layout.addWidget(self.output_path)
        layout.setAlignment(self.output_path, Qt.AlignHCenter)

        self.combo = QComboBox(content)
        self.combo.addItem("Graphviz dot")
        self.combo.addItem("Graph Modelling Language (gml)")
        self.combo.addItem("Json")
        layout.addWidget(self.combo)
        layout.setAlignment(self.combo, Qt.AlignHCenter)

        # TODO: This graph is not available due to an issue on radare2 (see closed issue #13590). It will be available as soon as Cutter updates its radare2 version.
        deep_button = QPushButton(content)
        deep_button.setText("Deep callgraph")
        deep_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        deep_button.setMaximumHeight(50)
        deep_button.setMaximumWidth(200)
        layout.addWidget(deep_button)
        layout.setAlignment(deep_button, Qt.AlignHCenter)

        global_button = QPushButton(content)
        global_button.setText("Global callgraph")
        global_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        global_button.setMaximumHeight(50)
        global_button.setMaximumWidth(200)
        layout.addWidget(global_button)
        layout.setAlignment(global_button, Qt.AlignHCenter)

        function_button = QPushButton(content)
        function_button.setText("Function callgraph")
        function_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        function_button.setMaximumHeight(50)
        function_button.setMaximumWidth(200)
        layout.addWidget(function_button)
        layout.setAlignment(function_button, Qt.AlignHCenter)

        global_data_x_button = QPushButton(content)
        global_data_x_button.setText("Global data references")
        global_data_x_button.setSizePolicy(QSizePolicy.Maximum,
                                           QSizePolicy.Maximum)
        global_data_x_button.setMaximumHeight(50)
        global_data_x_button.setMaximumWidth(200)
        layout.addWidget(global_data_x_button)
        layout.setAlignment(global_data_x_button, Qt.AlignHCenter)

        function_data_x_button = QPushButton(content)
        function_data_x_button.setText("Function data references")
        function_data_x_button.setSizePolicy(QSizePolicy.Maximum,
                                             QSizePolicy.Maximum)
        function_data_x_button.setMaximumHeight(50)
        function_data_x_button.setMaximumWidth(200)
        layout.addWidget(function_data_x_button)
        layout.setAlignment(function_data_x_button, Qt.AlignHCenter)

        global_refs_button = QPushButton(content)
        global_refs_button.setText("Global references")
        global_refs_button.setSizePolicy(QSizePolicy.Maximum,
                                         QSizePolicy.Maximum)
        global_refs_button.setMaximumHeight(50)
        global_refs_button.setMaximumWidth(200)
        layout.addWidget(global_refs_button)
        layout.setAlignment(global_refs_button, Qt.AlignHCenter)

        xrefs_button = QPushButton(content)
        xrefs_button.setText("Function xrefs")
        xrefs_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        xrefs_button.setMaximumHeight(50)
        xrefs_button.setMaximumWidth(200)
        layout.addWidget(xrefs_button)
        layout.setAlignment(xrefs_button, Qt.AlignHCenter)

        imports_button = QPushButton(content)
        imports_button.setText("Imports refs")
        imports_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        imports_button.setMaximumHeight(50)
        imports_button.setMaximumWidth(200)
        layout.addWidget(imports_button)
        layout.setAlignment(imports_button, Qt.AlignHCenter)

        QObject.connect(deep_button, SIGNAL("clicked()"),
                        self.generate_callgraph)
        QObject.connect(global_button, SIGNAL("clicked()"),
                        self.generate_global_callgraph)
        QObject.connect(function_button, SIGNAL("clicked()"),
                        self.generate_local_callgraph)
        QObject.connect(global_data_x_button, SIGNAL("clicked()"),
                        self.generate_global_data_references)
        QObject.connect(function_data_x_button, SIGNAL("clicked()"),
                        self.generate_local_data_references)
        QObject.connect(global_refs_button, SIGNAL("clicked()"),
                        self.generate_global_refs)
        QObject.connect(xrefs_button, SIGNAL("clicked()"), self.generate_xrefs)
        QObject.connect(imports_button, SIGNAL("clicked()"),
                        self.generate_imports_graph)

        self.show()

    def generate_callgraph(self):
        # TODO: get user settings for the .dot graph instead of using this hardcoded settings
        self.graph_dot = """digraph code {
        rankdir=LR;
        outputorder=edgesfirst;
        graph [bgcolor=azure fontname="Courier" splines="curved"];
        node [fillcolor=white style=filled fontname="Courier New Bold" fontsize=14 shape=box];
        edge [arrowhead="normal" style=bold weight=2];"""
        self.used_nodes = []
        function_name = cutter.cmd('afi.')
        function_name = function_name.replace("\n", "")
        self.functions_list = cutter.cmdj('aflmj')
        self.get_calls(function_name)
        self.graph_dot += '\n}'

    def add_node(self, name):
        if name not in self.used_nodes:
            self.used_nodes.append(name)
            self.graph_dot += '\n"' + name + '" [label="' + name + '"];'

    def add_edge(self, name1, name2):
        self.graph_dot += '\n"' + name1 + '" -> "' + name2 + '" [color="#61afef"];'

    def get_calls(self, name):
        self.add_node(name)
        for function in self.functions_list:
            if function['name'] == name:
                for call in function['calls']:
                    self.add_node(call['name'])
                    self.add_edge(name, call['name'])
                    if call['name'][:3] != 'sym':
                        self.get_calls(call['name'])

    def output_callgraph(self):
        output = 'deep_callgraph_' + cutter.cmd(
            'afi.') + self.get_output_format_extension(
                self.combo.currentIndex())
        file = open(output, "w")
        file.write(self.graph_dot)
        file.close()

    def generate_global_callgraph(self):
        # agC
        name = self.get_output_name("global_callgraph")
        command = "agC" + self.get_output_format_cmd(self.combo.currentIndex())
        cutter.cmd(command + " > " + name)

    def generate_local_callgraph(self):
        # agc
        function_name = self.get_output_name("callgraph", function=True)
        command = "agc" + self.get_output_format_cmd(self.combo.currentIndex())
        command += " > "
        command += function_name
        cutter.cmd(command)

    def generate_global_data_references(self):
        # agA
        name = self.get_output_name("global_data_references")
        command = "agA" + self.get_output_format_cmd(self.combo.currentIndex())
        cutter.cmd(command + " > " + name)

    def generate_local_data_references(self):
        # aga
        function_name = self.get_output_name("data_references", function=True)
        command = "aga" + self.get_output_format_cmd(self.combo.currentIndex())
        command += " > "
        command += function_name
        cutter.cmd(command)

    def generate_global_refs(self):
        # agR
        name = self.get_output_name("global_references")
        command = "agR" + self.get_output_format_cmd(self.combo.currentIndex())
        cutter.cmd(command + " > " + name)

    def generate_xrefs(self):
        # agx
        function_name = self.get_output_name("xrefs", function=True)
        command = "agx" + self.get_output_format_cmd(self.combo.currentIndex())
        command += " > "
        command += function_name
        cutter.cmd(command)

    def generate_imports_graph(self):
        # agi
        name = self.get_output_name("imports_refs")
        command = "agi" + self.get_output_format_cmd(self.combo.currentIndex())
        cutter.cmd(command + " > " + name)

    def get_output_name(self, graph_name, function=False):
        if not function:
            name = graph_name + "." + self.get_output_format_extension(
                self.combo.currentIndex())
            return self.append_to_path(name)
        else:
            function_name = cutter.cmd('afi.')
            function_name = function_name.replace("\n", "")
            function_name += "_"
            function_name += graph_name
            function_name += "."
            function_name += self.get_output_format_extension(
                self.combo.currentIndex())
            return self.append_to_path(function_name)

    def append_to_path(self, name):
        path = self.output_path.text()
        if path != "PATH":
            if path[-1:] != '/':
                path += '/'
            name = str(path) + name
        return name

    def get_output_format_extension(self, index):
        if index == 0:
            return "dot"
        elif index == 1:
            return "gml"
        elif index == 2:
            return "json"
        else:
            return "none"

    def get_output_format_cmd(self, index):
        if index == 0:
            return "d"
        elif index == 1:
            return "g"
        elif index == 2:
            return "j"
        else:
            return ""
Пример #14
0
def refresh_if_needed(combo: QtWidgets.QComboBox, func):
    if combo.currentIndex() == 0:
        func(0)
Пример #15
0
class QSettingsWindow(QDialog):

    def __init__(self, game: Game):
        super(QSettingsWindow, self).__init__()

        self.game = game

        self.setModal(True)
        self.setWindowTitle("Settings")
        self.setWindowIcon(CONST.ICONS["Settings"])
        self.setMinimumSize(600, 250)

        self.initUi()

    def initUi(self):
        self.layout = QGridLayout()

        self.categoryList = QListView()
        self.right_layout = QStackedLayout()

        self.categoryList.setMaximumWidth(175)

        self.categoryModel = QStandardItemModel(self.categoryList)

        difficulty = QStandardItem("Difficulty")
        difficulty.setIcon(CONST.ICONS["Missile"])
        difficulty.setEditable(False)
        difficulty.setSelectable(True)

        generator = QStandardItem("Mission Generator")
        generator.setIcon(CONST.ICONS["Generator"])
        generator.setEditable(False)
        generator.setSelectable(True)

        cheat = QStandardItem("Cheat Menu")
        cheat.setIcon(CONST.ICONS["Cheat"])
        cheat.setEditable(False)
        cheat.setSelectable(True)

        self.categoryList.setIconSize(QSize(32, 32))
        self.categoryModel.appendRow(difficulty)
        self.categoryModel.appendRow(generator)
        self.categoryModel.appendRow(cheat)

        self.categoryList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.categoryList.setModel(self.categoryModel)
        self.categoryList.selectionModel().setCurrentIndex(self.categoryList.indexAt(QPoint(1,1)), QItemSelectionModel.Select)
        self.categoryList.selectionModel().selectionChanged.connect(self.onSelectionChanged)

        self.initDifficultyLayout()
        self.initGeneratorLayout()
        self.initCheatLayout()

        self.right_layout.addWidget(self.difficultyPage)
        self.right_layout.addWidget(self.generatorPage)
        self.right_layout.addWidget(self.cheatPage)

        self.layout.addWidget(self.categoryList, 0, 0, 1, 1)
        self.layout.addLayout(self.right_layout, 0, 1, 5, 1)

        self.setLayout(self.layout)

    def init(self):
        pass

    def initDifficultyLayout(self):

        self.difficultyPage = QWidget()
        self.difficultyLayout = QGridLayout()
        self.difficultyLayout.setAlignment(Qt.AlignTop)
        self.difficultyPage.setLayout(self.difficultyLayout)

        self.playerCoalitionSkill = QComboBox()
        self.enemyCoalitionSkill = QComboBox()
        self.enemyAASkill = QComboBox()
        for skill in CONST.SKILL_OPTIONS:
            self.playerCoalitionSkill.addItem(skill)
            self.enemyCoalitionSkill.addItem(skill)
            self.enemyAASkill.addItem(skill)

        self.playerCoalitionSkill.setCurrentIndex(CONST.SKILL_OPTIONS.index(self.game.settings.player_skill))
        self.enemyCoalitionSkill.setCurrentIndex(CONST.SKILL_OPTIONS.index(self.game.settings.enemy_skill))
        self.enemyAASkill.setCurrentIndex(CONST.SKILL_OPTIONS.index(self.game.settings.enemy_vehicle_skill))

        self.playerCoalitionSkill.currentIndexChanged.connect(self.applySettings)
        self.enemyCoalitionSkill.currentIndexChanged.connect(self.applySettings)
        self.enemyAASkill.currentIndexChanged.connect(self.applySettings)

        self.difficultyLayout.addWidget(QLabel("Player coalition skill"), 0, 0)
        self.difficultyLayout.addWidget(self.playerCoalitionSkill, 0, 1, Qt.AlignRight)
        self.difficultyLayout.addWidget(QLabel("Enemy skill"), 1, 0)
        self.difficultyLayout.addWidget(self.enemyCoalitionSkill, 1, 1, Qt.AlignRight)
        self.difficultyLayout.addWidget(QLabel("Enemy AA and vehicles skill"), 2, 0)
        self.difficultyLayout.addWidget(self.enemyAASkill, 2, 1, Qt.AlignRight)

        self.difficultyLabel = QComboBox()
        [self.difficultyLabel.addItem(t) for t in CONST.LABELS_OPTIONS]
        self.difficultyLabel.setCurrentIndex(CONST.LABELS_OPTIONS.index(self.game.settings.labels))
        self.difficultyLabel.currentIndexChanged.connect(self.applySettings)

        self.difficultyLayout.addWidget(QLabel("In Game Labels"), 3, 0)
        self.difficultyLayout.addWidget(self.difficultyLabel, 3, 1, Qt.AlignRight)

        self.noNightMission = QCheckBox()
        self.noNightMission.setChecked(self.game.settings.night_disabled)
        self.noNightMission.toggled.connect(self.applySettings)
        self.difficultyLayout.addWidget(QLabel("No night missions"), 4, 0)
        self.difficultyLayout.addWidget(self.noNightMission, 4, 1, Qt.AlignRight)

        self.mapVisibiitySelection = QComboBox()
        self.mapVisibiitySelection.addItem("All", ForcedOptions.Views.All)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.All:
            self.mapVisibiitySelection.setCurrentIndex(0)
        self.mapVisibiitySelection.addItem("Fog of War", ForcedOptions.Views.Allies)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.Allies:
            self.mapVisibiitySelection.setCurrentIndex(1)
        self.mapVisibiitySelection.addItem("Allies Only", ForcedOptions.Views.OnlyAllies)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.OnlyAllies:
            self.mapVisibiitySelection.setCurrentIndex(2)
        self.mapVisibiitySelection.addItem("Own Aircraft Only", ForcedOptions.Views.MyAircraft)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.MyAircraft:
            self.mapVisibiitySelection.setCurrentIndex(3)
        self.mapVisibiitySelection.addItem("Map Only", ForcedOptions.Views.OnlyMap)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.OnlyMap:
            self.mapVisibiitySelection.setCurrentIndex(4)
        self.mapVisibiitySelection.currentIndexChanged.connect(self.applySettings)
        self.difficultyLayout.addWidget(QLabel("Map visibility options"), 5, 0)
        self.difficultyLayout.addWidget(self.mapVisibiitySelection, 5, 1, Qt.AlignRight)

        self.ext_views = QCheckBox()
        self.ext_views.setChecked(self.game.settings.external_views_allowed)
        self.ext_views.toggled.connect(self.applySettings)
        self.difficultyLayout.addWidget(QLabel("Allow external views"), 6, 0)
        self.difficultyLayout.addWidget(self.ext_views, 6, 1, Qt.AlignRight)


    def initGeneratorLayout(self):
        self.generatorPage = QWidget()
        self.generatorLayout = QVBoxLayout()
        self.generatorLayout.setAlignment(Qt.AlignTop)
        self.generatorPage.setLayout(self.generatorLayout)

        self.gameplay = QGroupBox("Gameplay")
        self.gameplayLayout = QGridLayout();
        self.gameplayLayout.setAlignment(Qt.AlignTop)
        self.gameplay.setLayout(self.gameplayLayout)

        self.supercarrier = QCheckBox()
        self.supercarrier.setChecked(self.game.settings.supercarrier)
        self.supercarrier.toggled.connect(self.applySettings)

        self.generate_marks = QCheckBox()
        self.generate_marks.setChecked(self.game.settings.generate_marks)
        self.generate_marks.toggled.connect(self.applySettings)


        if not hasattr(self.game.settings, "include_jtac_if_available"):
            self.game.settings.include_jtac_if_available = True

        self.include_jtac_if_available = QCheckBox()
        self.include_jtac_if_available.setChecked(self.game.settings.include_jtac_if_available)
        self.include_jtac_if_available.toggled.connect(self.applySettings)

        self.gameplayLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0)
        self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight)
        self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"), 1, 0)
        self.gameplayLayout.addWidget(self.generate_marks, 1, 1, Qt.AlignRight)
        self.gameplayLayout.addWidget(QLabel("Include JTAC (If available)"), 2, 0)
        self.gameplayLayout.addWidget(self.include_jtac_if_available, 2, 1, Qt.AlignRight)

        self.performance = QGroupBox("Performance")
        self.performanceLayout = QGridLayout()
        self.performanceLayout.setAlignment(Qt.AlignTop)
        self.performance.setLayout(self.performanceLayout)

        self.smoke = QCheckBox()
        self.smoke.setChecked(self.game.settings.perf_smoke_gen)
        self.smoke.toggled.connect(self.applySettings)

        self.red_alert = QCheckBox()
        self.red_alert.setChecked(self.game.settings.perf_red_alert_state)
        self.red_alert.toggled.connect(self.applySettings)

        self.arti = QCheckBox()
        self.arti.setChecked(self.game.settings.perf_artillery)
        self.arti.toggled.connect(self.applySettings)

        self.moving_units = QCheckBox()
        self.moving_units.setChecked(self.game.settings.perf_moving_units)
        self.moving_units.toggled.connect(self.applySettings)

        self.infantry = QCheckBox()
        self.infantry.setChecked(self.game.settings.perf_infantry)
        self.infantry.toggled.connect(self.applySettings)

        self.ai_parking_start = QCheckBox()
        self.ai_parking_start.setChecked(self.game.settings.perf_ai_parking_start)
        self.ai_parking_start.toggled.connect(self.applySettings)

        self.destroyed_units = QCheckBox()
        self.destroyed_units.setChecked(self.game.settings.perf_destroyed_units)
        self.destroyed_units.toggled.connect(self.applySettings)

        self.culling = QCheckBox()
        self.culling.setChecked(self.game.settings.perf_culling)
        self.culling.toggled.connect(self.applySettings)

        self.culling_distance = QSpinBox()
        self.culling_distance.setMinimum(50)
        self.culling_distance.setMaximum(10000)
        self.culling_distance.setValue(self.game.settings.perf_culling_distance)
        self.culling_distance.valueChanged.connect(self.applySettings)

        self.performanceLayout.addWidget(QLabel("Smoke visual effect on frontline"), 0, 0)
        self.performanceLayout.addWidget(self.smoke, 0, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("SAM starts in RED alert mode"), 1, 0)
        self.performanceLayout.addWidget(self.red_alert, 1, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Artillery strikes"), 2, 0)
        self.performanceLayout.addWidget(self.arti, 2, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Moving ground units"), 3, 0)
        self.performanceLayout.addWidget(self.moving_units, 3, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Generate infantry squads along vehicles"), 4, 0)
        self.performanceLayout.addWidget(self.infantry, 4, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("AI planes parking start (AI starts in flight if disabled)"), 5, 0)
        self.performanceLayout.addWidget(self.ai_parking_start, 5, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Include destroyed units carcass"), 6, 0)
        self.performanceLayout.addWidget(self.destroyed_units, 6, 1, alignment=Qt.AlignRight)

        self.performanceLayout.addWidget(QHorizontalSeparationLine(), 7, 0, 1, 2)
        self.performanceLayout.addWidget(QLabel("Culling of distant units enabled"), 8, 0)
        self.performanceLayout.addWidget(self.culling, 8, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 9, 0)
        self.performanceLayout.addWidget(self.culling_distance, 9, 1, alignment=Qt.AlignRight)

        self.generatorLayout.addWidget(self.gameplay)
        self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience."))
        self.generatorLayout.addWidget(self.performance)


    def initCheatLayout(self):

        self.cheatPage = QWidget()
        self.cheatLayout = QGridLayout()
        self.cheatPage.setLayout(self.cheatLayout)

        self.moneyCheatBox = QGroupBox("Money Cheat")
        self.moneyCheatBox.setAlignment(Qt.AlignTop)
        self.moneyCheatBoxLayout = QGridLayout()
        self.moneyCheatBox.setLayout(self.moneyCheatBoxLayout)

        self.cheat25M = QPushButton("Cheat +25M")
        self.cheat50M = QPushButton("Cheat +50M")
        self.cheat100M = QPushButton("Cheat +100M")
        self.cheat200M = QPushButton("Cheat +200M")
        self.cheat500M = QPushButton("Cheat +500M")
        self.cheat1000M = QPushButton("Cheat +1000M")

        self.cheat25M.clicked.connect(lambda: self.cheatMoney(25))
        self.cheat50M.clicked.connect(lambda: self.cheatMoney(50))
        self.cheat100M.clicked.connect(lambda: self.cheatMoney(100))
        self.cheat200M.clicked.connect(lambda: self.cheatMoney(200))
        self.cheat500M.clicked.connect(lambda: self.cheatMoney(500))
        self.cheat1000M.clicked.connect(lambda: self.cheatMoney(1000))

        self.moneyCheatBoxLayout.addWidget(self.cheat25M, 0, 0)
        self.moneyCheatBoxLayout.addWidget(self.cheat50M, 0, 1)
        self.moneyCheatBoxLayout.addWidget(self.cheat100M, 1, 0)
        self.moneyCheatBoxLayout.addWidget(self.cheat200M, 1, 1)
        self.moneyCheatBoxLayout.addWidget(self.cheat500M, 2, 0)
        self.moneyCheatBoxLayout.addWidget(self.cheat1000M, 2, 1)

        self.cheatLayout.addWidget(self.moneyCheatBox, 0, 0)

    def cheatMoney(self, amount):
        self.game.budget += amount
        self.game.informations.append(Information("CHEATER", "You are a cheater and you should feel bad", self.game.turn))
        GameUpdateSignal.get_instance().updateGame(self.game)

    def applySettings(self):
        self.game.settings.player_skill = CONST.SKILL_OPTIONS[self.playerCoalitionSkill.currentIndex()]
        self.game.settings.enemy_skill = CONST.SKILL_OPTIONS[self.enemyCoalitionSkill.currentIndex()]
        self.game.settings.enemy_vehicle_skill = CONST.SKILL_OPTIONS[self.enemyAASkill.currentIndex()]
        self.game.settings.labels = CONST.LABELS_OPTIONS[self.difficultyLabel.currentIndex()]
        self.game.settings.night_disabled = self.noNightMission.isChecked()
        self.game.settings.map_coalition_visibility = self.mapVisibiitySelection.currentData()
        self.game.settings.external_views_allowed = self.ext_views.isChecked()
        self.game.settings.generate_marks = self.generate_marks.isChecked()
        self.game.settings.include_jtac_if_available = self.include_jtac_if_available.isChecked()

        print(self.game.settings.map_coalition_visibility)

        self.game.settings.supercarrier = self.supercarrier.isChecked()

        self.game.settings.perf_red_alert_state = self.red_alert.isChecked()
        self.game.settings.perf_smoke_gen = self.smoke.isChecked()
        self.game.settings.perf_artillery = self.arti.isChecked()
        self.game.settings.perf_moving_units = self.moving_units.isChecked()
        self.game.settings.perf_infantry = self.infantry.isChecked()
        self.game.settings.perf_ai_parking_start = self.ai_parking_start.isChecked()
        self.game.settings.perf_destroyed_units = self.destroyed_units.isChecked()

        self.game.settings.perf_culling = self.culling.isChecked()
        self.game.settings.perf_culling_distance = int(self.culling_distance.value())

        GameUpdateSignal.get_instance().updateGame(self.game)

    def onSelectionChanged(self):
        index = self.categoryList.selectionModel().currentIndex().row()
        self.right_layout.setCurrentIndex(index)
Пример #16
0
class MainWindow(QMainWindow):  # Main window
    def __init__(self):
        super().__init__()
        self.setWindowTitle = 'DD烤肉机'
        self.resize(1870, 820)
        self.mainWidget = QWidget()
        self.mainLayout = QGridLayout()  # Grid layout
        self.mainLayout.setSpacing(10)
        self.mainWidget.setLayout(self.mainLayout)
        self.duration = 60000
        self.bitrate = 2000
        self.fps = 60

        self.initProcess = InitProcess()
        self.previewSubtitle = PreviewSubtitle()
        self.dnldWindow = YoutubeDnld()
        self.exportWindow = exportSubtitle()
        self.videoDecoder = VideoDecoder()
        self.exportWindow.exportArgs.connect(self.exportSubtitle)
        self.stack = QStackedWidget()
        self.stack.setFixedWidth(1300)
        self.mainLayout.addWidget(self.stack, 0, 0, 10, 8)
        buttonWidget = QWidget()
        buttonLayout = QHBoxLayout()
        buttonWidget.setLayout(buttonLayout)
        self.playButton = QPushButton('从本地打开')
        self.playButton.clicked.connect(self.open)
        self.playButton.setFixedWidth(400)
        self.playButton.setFixedHeight(75)
        self.dnldButton = QPushButton('Youtube下载器')
        self.dnldButton.clicked.connect(self.popDnld)
        self.dnldButton.setFixedWidth(400)
        self.dnldButton.setFixedHeight(75)
        buttonLayout.addWidget(self.playButton)
        buttonLayout.addWidget(self.dnldButton)
        self.stack.addWidget(buttonWidget)

        self.videoPath = ''
        self.videoWidth = 1920
        self.videoHeight = 1080
        self.globalInterval = 200
        self.setPlayer()
        self.setSubtitle()
        self.setToolBar()
        self.setCentralWidget(self.mainWidget)
        self.playStatus = False
        self.volumeStatus = True
        self.volumeValue = 100
        self.subSelectedTxt = ''
        self.subReplayTime = 1
        self.clipBoard = []
        self.grabKeyboard()
        self.show()

    def setPlayer(self):
        self.playerWidget = QGraphicsVideoItem()
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.view.resize(1280, 730)
        self.scene.addItem(self.playerWidget)
        self.stack.addWidget(self.view)
        self.player = QMediaPlayer(self, QMediaPlayer.VideoSurface)
        self.player.setVideoOutput(self.playerWidget)
        self.view.installEventFilter(self)
        self.view.show()
        self.srtTextItemDict = {0: QGraphicsTextItem(), 1: QGraphicsTextItem(), 2: QGraphicsTextItem(), 3: QGraphicsTextItem(), 4: QGraphicsTextItem()}
        for _, srtTextItem in self.srtTextItemDict.items():
            self.scene.addItem(srtTextItem)

    def setSubtitle(self):
        self.subtitleDict = {x: {-1: [100, '']} for x in range(5)}
        self.subTimer = QTimer()
        self.subTimer.setInterval(100)
        self.subtitle = QTableWidget()
        self.subtitle.setAutoScroll(False)
        self.subtitle.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.mainLayout.addWidget(self.subtitle, 0, 8, 10, 12)
        self.subtitle.setColumnCount(5)
        self.subtitle.selectRow(0)
        self.subtitle.setHorizontalHeaderLabels(['%s' % (i + 1) for i in range(5)])
        self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
        for index in range(5):
            self.subtitle.setColumnWidth(index, 130)
        self.subtitle.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.subtitle.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.subtitle.horizontalHeader().sectionClicked.connect(self.addSubtitle)
        self.subtitle.doubleClicked.connect(self.releaseKeyboard)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.subtitle.verticalHeader().sectionClicked.connect(self.subHeaderClick)
        self.subtitle.setContextMenuPolicy(Qt.CustomContextMenu)
        self.subtitle.customContextMenuRequested.connect(self.popTableMenu)
        self.initSubtitle()

    def initSubtitle(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for x in range(self.subtitle.columnCount()):
            for y in range(self.subtitle.rowCount()):
                self.subtitle.setSpan(y, x, 1, 1)
        self.subtitle.setRowCount(self.duration // self.globalInterval + 1)
        for x in range(self.subtitle.columnCount()):
            for y in range(self.subtitle.rowCount()):
                self.subtitle.setItem(y, x, QTableWidgetItem(''))
                self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
        self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def addSubtitle(self, index):
        subtitlePath = QFileDialog.getOpenFileName(self, "请选择字幕", None, "字幕文件 (*.srt *.vtt *.ass *.ssa)")[0]
        if subtitlePath:
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            if subtitlePath.endswith('.ass') or subtitlePath.endswith('.ssa'):
                p = subprocess.Popen(['utils/ffmpeg.exe', '-y', '-i', subtitlePath, 'temp_sub.srt'])
                p.wait()
                subtitlePath = 'temp_sub.srt'
            subData = {}
            with open(subtitlePath, 'r', encoding='utf-8') as f:
                f = f.readlines()
            subText = ''
            YoutubeAutoSub = False
            for l in f:
                if '<c>' in l:
                    YoutubeAutoSub = True
                    break
            for cnt, l in enumerate(f):
                if '<c>' in l:
                    lineData = l.split('c>')
                    if len(lineData) > 3:
                        subText, start, _ = lineData[0].split('<')
                        start = calSubTime(start[:-1]) // self.globalInterval * self.globalInterval
                        if start not in self.subtitleDict[index]:
                            end = calSubTime(lineData[-3][1:-2]) // self.globalInterval * self.globalInterval
                            for i in range(len(lineData) // 2):
                                subText += lineData[i * 2 + 1][:-2]
                            subData[start] = [end - start, subText]
                    else:
                        subText, start, _ = lineData[0].split('<')
                        start = calSubTime(start[:-1]) // self.globalInterval * self.globalInterval
                        if start not in self.subtitleDict[index]:
                            subText += lineData[1][:-2]
                            subData[start] = [self.globalInterval, subText]
                elif '-->' in l and f[cnt + 2].strip() and '<c>' not in f[cnt + 2]:
                    subText = f[cnt + 2][:-1]
                    start = calSubTime(l[:12]) // self.globalInterval * self.globalInterval
                    if start not in self.subtitleDict[index]:
                        end = calSubTime(l[17:29]) // self.globalInterval * self.globalInterval
                        subData[start] = [end - start, subText]
                if '-->' in l and f[cnt + 1].strip() and not YoutubeAutoSub:
                    start = calSubTime(l[:12]) // self.globalInterval * self.globalInterval
                    if start not in self.subtitleDict[index]:
                        end = calSubTime(l[17:29]) // self.globalInterval * self.globalInterval
                        delta = end - start
                        if delta > 10:
                            if '<b>' in f[cnt + 1]:
                                subData[start] = [delta, f[cnt + 1].split('<b>')[1].split('<')[0]]
                            else:
                                subData[start] = [delta, f[cnt + 1][:-1]]
            self.subtitleDict[index].update(subData)
            maxRow = 0
            for _, v in self.subtitleDict.items():
                startMax = max(v.keys())
                rowCount = (startMax + v[startMax][0]) // self.globalInterval
                if rowCount > maxRow:
                    maxRow = rowCount
            if maxRow < self.duration // self.globalInterval + 1:
                maxRow = self.duration // self.globalInterval
            else:
                self.duration = maxRow * self.globalInterval
            self.subtitle.setRowCount(maxRow)
            self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
            for start, rowData in subData.items():
                startRow = start // self.globalInterval
                endRow = startRow + rowData[0] // self.globalInterval
                for row in range(startRow, endRow):
                    self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                    self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
                self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
            self.refreshComboBox()
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()

    def subTimeOut(self):
        fontColor = self.previewSubtitle.fontColor
        fontSize = (self.previewSubtitle.fontSize + 5) / 2.5
        fontBold = self.previewSubtitle.bold
        fontItalic = self.previewSubtitle.italic
        fontShadowOffset = self.previewSubtitle.shadowOffset
        for _, srtTextItem in self.srtTextItemDict.items():
            srtTextItem.setDefaultTextColor(fontColor)
            font = QFont()
            font.setFamily("微软雅黑")
            font.setPointSize(fontSize)
            font.setBold(fontBold)
            font.setItalic(fontItalic)
            srtTextItem.setFont(font)
            srtTextShadow = QGraphicsDropShadowEffect()
            srtTextShadow.setOffset(fontShadowOffset)
            srtTextItem.setGraphicsEffect(srtTextShadow)
        try:
            selected = self.subtitle.selectionModel().selection().indexes()
            for x, i in enumerate(selected):
                if self.subtitle.item(i.row(), x):
                    txt = self.subtitle.item(i.row(), x).text()
                    if txt:
                        self.srtTextItemDict[x].setPlainText('#%s:' % (x + 1) + txt)
                        txtSize = self.srtTextItemDict[x].boundingRect().size()
                        posY = self.playerWidget.size().height() - txtSize.height() * (x + 1)
                        posX = (self.playerWidget.size().width() - txtSize.width()) / 2
                        self.srtTextItemDict[x].setPos(posX, posY)
                    else:
                        self.srtTextItemDict[x].setPlainText('')
                else:
                    self.srtTextItemDict[x].setPlainText('')
        except:
            pass

    def subHeaderClick(self, index):
        if self.player.duration():
            position = index * self.globalInterval
            self.player.setPosition(position)
            self.videoSlider.setValue(position * 1000 // self.player.duration())
            self.setTimeLabel()

    def subEdit(self, row, index):
        repeat = self.subtitle.rowSpan(row, index)
        self.setSubtitleDict(row, index, repeat, self.subtitle.item(row, index).text())
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for cnt in range(repeat):
            if self.subtitle.item(row + cnt, index).text():
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            else:
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#232629')))
        self.subtitle.cellChanged.connect(self.subEdit)

    def setSubtitleDict(self, row, index, num, text):
        self.subtitleDict[index][row * self.globalInterval] = [num * self.globalInterval, text]

    def popTableMenu(self, pos):
        self.subtitle.cellChanged.disconnect(self.subEdit)
        pos = QPoint(pos.x() + 55, pos.y() + 30)
        menu = QMenu()
        copy = menu.addAction('复制')
        paste = menu.addAction('粘贴')
        setSpan = menu.addAction('合并')
        clrSpan = menu.addAction('拆分')
        addSub = menu.addAction('导入字幕')
        cutSub = menu.addAction('裁剪字幕')
        action = menu.exec_(self.subtitle.mapToGlobal(pos))
        selected = self.subtitle.selectionModel().selection().indexes()
        yList = [selected[0].row(), selected[-1].row()]
        xSet = set()
        for i in range(len(selected)):
            xSet.add(selected[i].column())
        if action == copy:
            for x in xSet:
                self.clipBoard = []
                for y in range(yList[0], yList[1] + 1):
                    if self.subtitle.item(y, x):
                        self.clipBoard.append(self.subtitle.item(y, x).text())
                    else:
                        self.clipBoard.append('')
                break
        elif action == paste:
            self.subtitle.cellChanged.connect(self.subEdit)
            for x in xSet:
                for cnt, text in enumerate(self.clipBoard):
                    self.subtitle.setItem(yList[0] + cnt, x, QTableWidgetItem(text))
                    self.subtitleDict[x][(yList[0] + cnt) * self.globalInterval] = [self.globalInterval, text]
            self.subtitle.cellChanged.disconnect(self.subEdit)
        elif action == setSpan:
            for x in xSet:
                if not self.subtitle.item(yList[0], x):
                    firstItem = ''
                else:
                    firstItem = self.subtitle.item(yList[0], x).text()
                for y in range(yList[0], yList[1] + 1):
                    self.subtitle.setSpan(y, x, 1, 1)
                    self.subtitle.setItem(y, x, QTableWidgetItem(firstItem))
                    self.subtitle.item(y, x).setBackground(QBrush(QColor('#35545d')))
                    if y * self.globalInterval in self.subtitleDict[x]:
                        del self.subtitleDict[x][y * self.globalInterval]
            for x in xSet:
                self.subtitle.setSpan(yList[0], x, yList[1] - yList[0] + 1, 1)
            self.setSubtitleDict(yList[0], x, yList[1] - yList[0] + 1, firstItem)
        elif action == clrSpan:
            for x in xSet:
                if not self.subtitle.item(yList[0], x):
                    firstItem = ''
                else:
                    firstItem = self.subtitle.item(yList[0], x).text()
                for cnt, y in enumerate(range(yList[0], yList[1] + 1)):
                    self.subtitle.setSpan(y, x, 1, 1)
                    if not cnt:
                        self.subtitle.setItem(yList[0], x, QTableWidgetItem(firstItem))
                        if firstItem:
                            self.subtitle.item(y, x).setBackground(QBrush(QColor('#35545d')))
                        else:
                            self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
                    else:
                        self.subtitle.setItem(y, x, QTableWidgetItem(''))
                        self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
                    self.setSubtitleDict(yList[0], x, yList[1] - yList[0] + 1, firstItem)
                break
        elif action == addSub:
            self.subtitle.cellChanged.connect(self.subEdit)
            for x in xSet:
                self.addSubtitle(x)
            self.subtitle.cellChanged.disconnect(self.subEdit)
        elif action == cutSub:
            for x in xSet:
                start = yList[0] * self.globalInterval
                end = yList[1] * self.globalInterval
                self.exportSubWindow(start, end, x + 1)
        self.subtitle.cellChanged.connect(self.subEdit)

    def setToolBar(self):
        '''
        menu bar, file menu, play menu, tool bar.
        '''
        toolBar = QToolBar()
        self.setContextMenuPolicy(Qt.NoContextMenu)
        self.addToolBar(toolBar)
        fileMenu = self.menuBar().addMenu('&文件')
        openAction = QAction(QIcon.fromTheme('document-open'), '&打开...', self, shortcut=QKeySequence.Open, triggered=self.open)
        fileMenu.addAction(openAction)
        downloadAction = QAction(QIcon.fromTheme('document-open'), '&Youtube下载器', self, triggered=self.popDnld)
        fileMenu.addAction(downloadAction)
        exitAction = QAction(QIcon.fromTheme('application-exit'), '&退出', self, shortcut='Ctrl+Q', triggered=self.close)
        fileMenu.addAction(exitAction)

        playMenu = self.menuBar().addMenu('&功能')
        self.playIcon = self.style().standardIcon(QStyle.SP_MediaPlay)
        self.pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause)
        self.playAction = toolBar.addAction(self.playIcon, '播放')
        self.playAction.triggered.connect(self.mediaPlay)
        self.volumeIcon = self.style().standardIcon(QStyle.SP_MediaVolume)
        self.volumeMuteIcon = self.style().standardIcon(QStyle.SP_MediaVolumeMuted)
        self.volumeAction = toolBar.addAction(self.volumeIcon, '静音')
        self.volumeAction.triggered.connect(self.volumeMute)
        previewAction = QAction(QIcon.fromTheme('document-open'), '&设置预览字幕', self, triggered=self.popPreview)
        playMenu.addAction(previewAction)

        decodeMenu = self.menuBar().addMenu('&输出')
        decodeAction = QAction(QIcon.fromTheme('document-open'), '&输出字幕及视频', self, triggered=self.decode)
        decodeMenu.addAction(decodeAction)

        self.volSlider = Slider()
        self.volSlider.setOrientation(Qt.Horizontal)
        self.volSlider.setMinimum(0)
        self.volSlider.setMaximum(100)
        self.volSlider.setFixedWidth(120)
        self.volSlider.setValue(self.player.volume())
        self.volSlider.setToolTip(str(self.volSlider.value()))
        self.volSlider.pointClicked.connect(self.setVolume)
        toolBar.addWidget(self.volSlider)

        self.videoPositionEdit = LineEdit('00:00')
        self.videoPositionEdit.setAlignment(Qt.AlignRight)
        self.videoPositionEdit.setFixedWidth(75)
        self.videoPositionEdit.setFont(QFont('Timers', 14))
        self.videoPositionEdit.clicked.connect(self.mediaPauseOnly)
        self.videoPositionEdit.editingFinished.connect(self.mediaPlayOnly)
        self.videoPositionLabel = QLabel(' / 00:00  ')
        self.videoPositionLabel.setFont(QFont('Timers', 14))
        toolBar.addWidget(QLabel('    '))
        toolBar.addWidget(self.videoPositionEdit)
        toolBar.addWidget(self.videoPositionLabel)

        self.timer = QTimer()
        self.timer.setInterval(100)
        self.videoSlider = Slider()
        self.videoSlider.setEnabled(False)
        self.videoSlider.setOrientation(Qt.Horizontal)
        self.videoSlider.setMinimum(0)
        self.videoSlider.setMaximum(1000)
        self.videoSlider.setFixedWidth(1000)
        self.videoSlider.sliderMoved.connect(self.timeStop)
        self.videoSlider.sliderReleased.connect(self.timeStart)
        self.videoSlider.pointClicked.connect(self.videoSliderClick)
        toolBar.addWidget(self.videoSlider)

        toolBar.addWidget(QLabel('   '))
        self.globalIntervalComBox = QComboBox()
        self.globalIntervalComBox.addItems(['间隔 100ms', '间隔 200ms', '间隔 500ms', '间隔 1s'])
        self.globalIntervalComBox.setCurrentIndex(1)
        self.globalIntervalComBox.currentIndexChanged.connect(self.setGlobalInterval)
        toolBar.addWidget(self.globalIntervalComBox)
        toolBar.addWidget(QLabel('  '))
        self.subEditComBox = QComboBox()
        self.refreshComboBox()
        toolBar.addWidget(self.subEditComBox)
        toolBar.addWidget(QLabel('  '))
        moveForward = QPushButton('- 1')
        moveForward.setFixedWidth(50)
        toolBar.addWidget(moveForward)
        toolBar.addWidget(QLabel('  '))
        moveAfterward = QPushButton('+ 1')
        moveAfterward.setFixedWidth(50)
        toolBar.addWidget(moveAfterward)
        toolBar.addWidget(QLabel('  '))
        clearSub = QPushButton('清空')
        clearSub.setFixedWidth(50)
        toolBar.addWidget(clearSub)
        toolBar.addWidget(QLabel('  '))
        outputSub = QPushButton('裁剪')
        outputSub.setFixedWidth(50)
        toolBar.addWidget(outputSub)
        moveForward.clicked.connect(self.moveForward)
        moveAfterward.clicked.connect(self.moveAfterward)
        clearSub.clicked.connect(self.clearSub)
        outputSub.clicked.connect(self.exportSubWindow)

    def setGlobalInterval(self, index):
        if not self.playStatus:
            self.mediaPlay()
        self.globalInterval = {0: 100, 1: 200, 2: 500, 3: 1000}[index]
        self.initSubtitle()
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for index, subData in self.subtitleDict.items():
            for start, rowData in subData.items():
                startRow = start // self.globalInterval
                deltaRow = rowData[0] // self.globalInterval
                if deltaRow:
                    endRow = startRow + deltaRow
                    for row in range(startRow, endRow):
                        self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                        if row >= 0:
                            self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
                    self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def moveForward(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        index = self.subEditComBox.currentIndex()
        for y in range(self.subtitle.rowCount()):
            self.subtitle.setSpan(y, index, 1, 1)
            self.subtitle.setItem(y, index, QTableWidgetItem(''))
            self.subtitle.item(y, index).setBackground(QBrush(QColor('#232629')))
        tmpDict = self.subtitleDict[index]
        self.subtitleDict[index] = {}
        for start, rowData in tmpDict.items():
            self.subtitleDict[index][start - self.globalInterval] = rowData
        for start, rowData in self.subtitleDict[index].items():
            startRow = start // self.globalInterval
            endRow = startRow + rowData[0] // self.globalInterval
            for row in range(startRow, endRow):
                self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def moveAfterward(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        index = self.subEditComBox.currentIndex()
        for y in range(self.subtitle.rowCount()):
            self.subtitle.setSpan(y, index, 1, 1)
            self.subtitle.setItem(y, index, QTableWidgetItem(''))
            self.subtitle.item(y, index).setBackground(QBrush(QColor('#232629')))
        tmpDict = self.subtitleDict[index]
        self.subtitleDict[index] = {}
        for start, rowData in tmpDict.items():
            self.subtitleDict[index][start + self.globalInterval] = rowData
        for start, rowData in self.subtitleDict[index].items():
            startRow = start // self.globalInterval
            endRow = startRow + rowData[0] // self.globalInterval
            for row in range(startRow, endRow):
                self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def clearSub(self):
        index = self.subEditComBox.currentIndex()
        reply = QMessageBox.information(self, '清空字幕', '清空第 %s 列字幕条?' % (index + 1), QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            self.subtitleDict[index] = {0: [self.globalInterval, '']}
            for i in range(self.subtitle.rowCount()):
                self.subtitle.setSpan(i, index, 1, 1)
                self.subtitle.setItem(i, index, QTableWidgetItem(''))
                self.subtitle.item(i, index).setBackground(QBrush(QColor('#232629')))
                self.subtitle.setHorizontalHeaderItem(index, QTableWidgetItem('%s' % (index + 1)))
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()

    def exportSubWindow(self, start=0, end=0, index=None):
        self.releaseKeyboard()
        self.exportWindow.hide()
        self.exportWindow.show()
        start = '00:00.0' if not start else self.splitTime(start)
        end = self.splitTime(self.duration) if not end else self.splitTime(end)
        if not index:
            index = self.subEditComBox.currentIndex() + 1
        self.exportWindow.setDefault(start, end, index)

    def exportSubtitle(self, exportArgs):
        start = calSubTime2(exportArgs[0])
        end = calSubTime2(exportArgs[1])
        subStart = calSubTime2(exportArgs[2])
        index = exportArgs[3] - 1
        subData = self.subtitleDict[index]
        rowList = sorted(subData.keys())
        exportRange = []
        for t in rowList:
            if t >= start and t <= end:
                exportRange.append(t)
        subNumber = 1
        with open(exportArgs[-1], 'w', encoding='utf-8') as exportFile:
            for t in exportRange:
                text = subData[t][1]
                if text:
                    start = ms2Time(t + subStart)
                    end = ms2Time(t + subStart + subData[t][0])
                    exportFile.write('%s\n%s --> %s\n%s\n\n' % (subNumber, start, end, text))
                    subNumber += 1
        QMessageBox.information(self, '导出字幕', '导出完成', QMessageBox.Yes)
        self.exportWindow.hide()

    def refreshComboBox(self):
        self.subEditComBox.clear()
        for i in range(self.subtitle.columnCount()):
            self.subEditComBox.addItem('字幕 ' + str(i + 1))

    def open(self):
        self.videoPath = QFileDialog.getOpenFileName(self, "请选择视频文件", None, "MP4格式 (*.mp4);;所有文件(*.*)")[0]
        if self.videoPath:
            cmd = ['utils/ffmpeg.exe', '-i', self.videoPath]
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            p.wait()
            for l in p.stdout.readlines():
                l = l.decode('utf8')
                if 'Duration' in l:
                    self.duration = calSubTime(l.split(' ')[3][:-1])
                if 'Stream' in l and 'DAR' in l:
                    self.videoWidth, self.videoHeight = map(int, l.split(' [')[0].split(' ')[-1].split('x'))
                    args = l.split(',')
                    for cnt, arg in enumerate(args):
                        if 'kb' in arg:
                            self.bitrate = int(arg.split('kb')[0])
                            self.fps = int(args[cnt + 1].split('fps')[0])
                            break
                    break
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            self.subtitle.setRowCount(self.duration // self.globalInterval + 1)
            self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()
            url = QUrl.fromLocalFile(self.videoPath)
            self.stack.setCurrentIndex(1)
            self.playerWidget.setSize(QSizeF(1280, 720))
            self.player.setMedia(url)
            self.playStatus = True
            self.videoSlider.setEnabled(True)
            self.mediaPlay()
            self.timer.start()
            self.timer.timeout.connect(self.timeOut)
            self.subTimer.start()
            self.subTimer.timeout.connect(self.subTimeOut)

    def popDnld(self):
        self.releaseKeyboard()
        self.dnldWindow.hide()
        self.dnldWindow.show()

    def popPreview(self):
        self.releaseKeyboard()
        self.previewSubtitle.hide()
        self.previewSubtitle.show()

    def decode(self):
        self.releaseKeyboard()
        self.videoDecoder.setDefault(self.videoPath, self.videoWidth, self.videoHeight, self.duration, self.bitrate, self.fps, self.subtitleDict)
        self.videoDecoder.hide()
        self.videoDecoder.show()

    def mediaPlay(self):
        if self.playStatus:
            self.player.play()
            self.grabKeyboard()
            self.timeStart()
            self.playStatus = False
            self.playAction.setIcon(self.pauseIcon)
            self.playAction.setText('暂停')
        else:
            self.player.pause()
            self.timeStop()
            self.playStatus = True
            self.playAction.setIcon(self.playIcon)
            self.playAction.setText('播放')

    def mediaPlayOnly(self):
        self.grabKeyboard()
        try:
            timeText = self.videoPositionEdit.text().split(':')
            m, s = timeText[:2]
            if not m:
                m = '00'
            if not s:
                s = '00'
            if len(m) > 3:
                m = m[:3]
            if len(s) > 2:
                s = s[:2]
            if m.isdigit():
                m = int(m)
            if s.isdigit():
                s = int(s)
            if s > 60:
                s = 60
            total_m = self.player.duration() // 60000
            if m > total_m:
                m = total_m
            self.player.setPosition(m * 60000 + s * 1000)
            self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
        except:
            pass
        self.videoPositionEdit.setReadOnly(True)
        self.timeStart()

    def mediaPauseOnly(self):
        self.releaseKeyboard()
        self.videoPositionEdit.setReadOnly(False)
        self.player.pause()
        self.timeStop()
        self.playStatus = True
        self.playAction.setIcon(self.playIcon)
        self.playAction.setText('播放')

    def splitTime(self, playTime):
        playTime = playTime // 1000
        m = str(playTime // 60)
        s = playTime % 60
        s = ('0%s' % s)[-2:]
        if len(m) > 2:
            t = '%3s:%2s' % (m, s)
        else:
            t = '%2s:%2s' % (m, s)
        return t

    def timeOut(self):
        row = self.player.position() // self.globalInterval
        self.subtitle.selectRow(row)
        self.subtitle.verticalScrollBar().setValue(row - 10)
        if self.dnldWindow.isHidden() or self.exportWindow.isHidden() or self.videoDecoder.isHidden():
            self.grabKeyboard()
        try:
            self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
            self.setTimeLabel()
        except:
            pass

    def timeStop(self):
        self.timer.stop()

    def timeStart(self):
        self.timer.start()

    def videoSliderClick(self, p):
        self.videoSlider.setValue(p.x())
        self.player.setPosition(p.x() * self.player.duration() // 1000)
        self.setTimeLabel()

    def setVolume(self, p):
        self.volumeValue = p.x()
        if self.volumeValue > 100:
            self.volumeValue = 100
        if self.volumeValue < 0:
            self.volumeValue = 0
        self.volSlider.setValue(self.volumeValue)
        self.player.setVolume(self.volumeValue)
        self.volSlider.setToolTip(str(self.volSlider.value()))
        if self.volumeValue:
            self.volumeStatus = True
            self.volumeAction.setIcon(self.volumeIcon)
        else:
            self.volumeStatus = False
            self.volumeAction.setIcon(self.volumeMuteIcon)

    def volumeMute(self):
        if self.volumeStatus:
            self.volumeStatus = False
            self.old_volumeValue = self.player.volume()
            self.player.setVolume(0)
            self.volSlider.setValue(0)
            self.volumeAction.setIcon(self.volumeMuteIcon)
        else:
            self.volumeStatus = True
            self.player.setVolume(self.old_volumeValue)
            self.volSlider.setValue(self.old_volumeValue)
            self.volumeAction.setIcon(self.volumeIcon)

    def setTimeLabel(self):
        now = self.player.position()
        total = self.player.duration()
        now = self.splitTime(now)
        total = self.splitTime(total)
        self.videoPositionEdit.setText(now)
        self.videoPositionLabel.setText(' / %s  ' % total)

    def eventFilter(self, obj, event):
        if obj == self.view:
            if event.type() == QEvent.MouseButtonPress:
                self.mediaPlay()
        return QMainWindow.eventFilter(self, obj, event)

    def keyPressEvent(self, QKeyEvent):
        key = QKeyEvent.key()
        if key == Qt.Key_Left:
            if self.videoSlider.isEnabled():
                self.player.setPosition(self.player.position() - 5000)
                self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
                self.setTimeLabel()
        elif key == Qt.Key_Right:
            if self.videoSlider.isEnabled():
                self.player.setPosition(self.player.position() + 5000)
                self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
                self.setTimeLabel()
        elif key == Qt.Key_Up:
            self.volumeValue += 10
            if self.volumeValue > 100:
                self.volumeValue = 100
            self.volSlider.setValue(self.volumeValue)
            self.player.setVolume(self.volumeValue)
        elif key == Qt.Key_Down:
            self.volumeValue -= 10
            if self.volumeValue < 0:
                self.volumeValue = 0
            self.volSlider.setValue(self.volumeValue)
            self.player.setVolume(self.volumeValue)
        elif key == Qt.Key_Space:
            self.mediaPlay()
Пример #17
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        def fun(spoiler):
            if spoiler.isOpened():
                spoiler.close()
            else:
                spoiler.open()

    # app = QApplication(sys.argv)

        w = QMainWindow()
        cw = QWidget()
        mainLayout = QHBoxLayout()
        cw.setLayout(mainLayout)

        gridLayout = QGridLayout()

        spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        gridLayout.addItem(spacerItem1, 0, 0, 1, 1)

        pushButton1 = QPushButton()
        pushButton1.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
        pushButton1.setText("")
        # gridLayout.addWidget(pushButton1, 0, 1, 1, 1)

        self.label1 = QLabel()
        self.label1.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        self.label1.setObjectName("")
        gridLayout.addWidget(self.label1, 0, 2, 1, 1)

        datePicker1 = DatePicker()
        gridLayout.addWidget(datePicker1, 0, 1, 1, 1)

        datePicker1.selectionChanged.connect(lambda: self.__setLableDate__(
            self.label1, datePicker1.selectedDate()))

        spacerItem2 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        gridLayout.addItem(spacerItem2, 0, 3, 1, 1)

        self.label2 = QLabel()
        self.label2.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        self.label2.setObjectName("")

        gridLayout.addWidget(self.label2, 0, 4, 1, 1)

        datePicker2 = DatePicker()
        gridLayout.addWidget(datePicker2, 0, 5, 1, 1)

        datePicker2.selectionChanged.connect(lambda: self.__setLableDate__(
            self.label2, datePicker2.selectedDate()))

        pushButton2 = QPushButton()
        pushButton2.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
        pushButton2.setText("")
        #gridLayout.addWidget(pushButton2, 0, 5, 1, 1)

        spacerItem3 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        gridLayout.addItem(spacerItem3, 0, 6, 1, 1)

        groupBox = QGroupBox()
        groupBox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
        verticalLayout = QVBoxLayout(groupBox)

        radioButton1 = QRadioButton(groupBox)
        radioButton1.setText("Subscribers")
        verticalLayout.addWidget(radioButton1)

        radioButton2 = QRadioButton(groupBox)
        radioButton1.setText("PatientsServices")
        verticalLayout.addWidget(radioButton2)

        export_btn = QPushButton()
        export_btn.setText("export")
        gridLayout.addWidget(export_btn)
        export_btn.clicked.connect(lambda: self.onExport_btn())

        gridLayout.addWidget(groupBox, 1, 1, 1, 2, Qt.AlignTop)

        self.comboBox = QComboBox()
        self.h_values = [
            "all", "مستشفي الصفوة الدولي", "مختبر مصراتة المركزي",
            "مستشفى الحكمه الحديث"
        ]
        self.comboBox.addItems(self.h_values)

        if self.comboBox.currentIndex() == 1:
            print("kln")

        self.comboBox.activated.connect(self.oncomboBoxChanged)

        gridLayout.addWidget(self.comboBox, 1, 4, 1, 2, Qt.AlignTop)

        btn = QPushButton("Click me")
        btn.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        spoiler = Spoiler(Spoiler.Orientation.VERTICAL)
        spoiler.setContentLayout(gridLayout)

        mainLayout.addWidget(btn)
        #self.searchGridLayout.addWidget(spoiler)

        # mainLayout.setAlignment(Qt.AlignRight)
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(716, 392)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setTabsClosable(False)
        self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
        self.InsertTab = QtWidgets.QWidget()
        self.InsertTab.setObjectName(_fromUtf8("InsertTab"))

        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.InsertTab)
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        spacerItem = QtWidgets.QSpacerItem(20, 109,
                                           QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_2.addItem(spacerItem)
        self.insertGridLayout = QtWidgets.QGridLayout()
        self.insertGridLayout.setObjectName(_fromUtf8("insertGridLayout"))
        self.runBtn = QtWidgets.QPushButton(self.InsertTab)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.runBtn.sizePolicy().hasHeightForWidth())
        self.runBtn.setSizePolicy(sizePolicy)
        self.runBtn.setMouseTracking(False)
        self.runBtn.setAutoFillBackground(False)
        self.runBtn.setStyleSheet(_fromUtf8("border: none"))
        self.runBtn.setText(_fromUtf8(""))
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(_fromUtf8("icons/run.png")),
                       QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.runBtn.setIcon(icon)
        self.runBtn.setIconSize(QtCore.QSize(64, 64))
        self.runBtn.setObjectName(_fromUtf8("runBtn"))
        self.insertGridLayout.addWidget(self.runBtn, 0, 3, 2, 1)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.combo = QComboBox()
        self.values = [
            "مستشفي الصفوة الدولي", "مختبر مصراتة المركزي",
            "مستشفى الحكمه الحديث", "مستشفى المدينه السكنيه"
        ]
        self.combo.addItems(self.values)

        if self.combo.currentIndex() == 1:
            print("kln")

        self.combo.activated.connect(self.oncomboChanged)

        self.insertGridLayout.addWidget(self.combo, 1, 4, 1, 2, Qt.AlignTop)
        self.insertGridLayout.addItem(spacerItem1, 0, 5, 1, 1)
        self.excelLabel = QtWidgets.QLabel(self.InsertTab)
        self.excelLabel.setText(_fromUtf8(""))
        self.excelLabel.setAlignment(QtCore.Qt.AlignRight
                                     | QtCore.Qt.AlignTrailing
                                     | QtCore.Qt.AlignVCenter)
        self.excelLabel.setObjectName(_fromUtf8("excelLabel"))
        self.insertGridLayout.addWidget(self.excelLabel, 1, 0, 1, 3)
        self.sqlBtn = QtWidgets.QPushButton(self.InsertTab)
        self.sqlBtn.setMinimumSize(QtCore.QSize(200, 0))
        self.sqlBtn.setObjectName(_fromUtf8("sqlBtn"))
        self.insertGridLayout.addWidget(self.sqlBtn, 0, 4, 1, 1)
        self.excelBtn = QtWidgets.QPushButton(self.InsertTab)
        self.excelBtn.setMinimumSize(QtCore.QSize(200, 0))
        self.excelBtn.setObjectName(_fromUtf8("excelBtn"))
        self.insertGridLayout.addWidget(self.excelBtn, 0, 2, 1, 1)
        spacerItem2 = QtWidgets.QSpacerItem(40, 20,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.insertGridLayout.addItem(spacerItem2, 0, 1, 1, 1)
        self.sqlLabel = QtWidgets.QLabel(self.InsertTab)
        self.sqlLabel.setText(_fromUtf8(""))
        self.sqlLabel.setObjectName(_fromUtf8("sqlLabel"))
        self.insertGridLayout.addWidget(self.sqlLabel, 1, 4, 1, 2)
        self.verticalLayout_2.addLayout(self.insertGridLayout)
        spacerItem3 = QtWidgets.QSpacerItem(20, 108,
                                            QtWidgets.QSizePolicy.Minimum,
                                            QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_2.addItem(spacerItem3)
        self.tabWidget.addTab(self.InsertTab, _fromUtf8(""))

        # self.filterBtn = QtWidgets.QPushButton(self.searchTab)
        # self.filterBtn.setStyleSheet(_fromUtf8("border: none"))
        # icon2 = QtGui.QIcon()
        # icon2.addPixmap(QtGui.QPixmap(_fromUtf8("icons/filter_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        # self.filterBtn.setIcon(icon2)
        # self.filterBtn.setObjectName(_fromUtf8("filterBtn"))
        # self.searchGridLayout.addWidget(self.filterBtn, 0, 3, 1, 1)
        # self.searchGridLayout.addWidget(spoiler)

        self.export_btn = QPushButton()
        self.export_btn.setText("export")
        #self.gridLayout.addWidget(export_btn)
        self.export_btn.clicked.connect(lambda: self.onExport_btnSubscribers())

        #self.exprt_btn = QtWidgets.QPushButton()

        #self.exprt_btn.setText("export")

        #self.exprt_btn.setObjectName(_fromUtf8("exprt_btn"))
        #self.searchGridLayout1.addWidget(self.exprt_btn, 0, 0, 2, 1)

        self.verticalLayout.addWidget(self.tabWidget)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(1)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.excelBtn.clicked.connect(MainWindow,
                                      QtCore.SLOT("onExcelBtnClick()"))
        self.sqlBtn.clicked.connect(MainWindow, QtCore.SLOT("onSqlBtnClick()"))
        self.runBtn.clicked.connect(MainWindow, QtCore.SLOT("onRunBtnClick()"))

        self.excelFileName = None
        self.sqlFileName = "/home/eamon/Desktop/test.sqlite"
        self.sqlLabel.setText(self.sqlFileName)
        conn = sqlite3.connect("C:\\Users\\PC WORLD\\Downloads\\test.sqlite")
        result = conn.execute("SELECT * FROM Subscribers")

        conn.close()

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.tabWidget.setToolTip(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-size:18pt;\">Search</span></p></body></html>",
                None))
        self.sqlBtn.setText(_translate("MainWindow", "select sql file", None))
        self.excelBtn.setText(
            _translate("MainWindow", "select exel file", None))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.InsertTab),
                                  _translate("MainWindow", "INSERT", None))

    def oncomboChanged(self, index):
        name = self.values[index]
        print(name)

    def oncomboBoxChanged(self, index):
        h_name = self.h_values[index]
        print(h_name)

    def onExport_btn(self):
        db = sqlite3.connect("/home/eamon/Desktop/test.sqlite")

        if self.h_values[self.comboBox.currentIndex()] != "all":
            date1 = (self.label1.text())
            date2 = (self.label2.text())

            format_date1 = "%Y-%m-%d"
            out_date1 = datetime.strptime(date1, format_date1)
            print(out_date1)

            format_date2 = "%Y-%m-%d"
            out_date2 = datetime.strptime(date2, format_date2)
            print(out_date2)

            df1 = pd.read_sql_query(
                "SELECT * FROM PatientsServices WHERE HospitalName='%s' and date BETWEEN '%s' AND '%s'"
                % (self.h_values[self.comboBox.currentIndex()], out_date1,
                   out_date2), db)
            # df.to_excel('output.xlsx')

            # Create a Pandas Excel writer using XlsxWriter as the engine.
            writer = pd.ExcelWriter(
                self.h_values[self.comboBox.currentIndex()] + '.xlsx',
                engine='xlsxwriter')

            # Convert the dataframe to an XlsxWriter Excel object.
            df1.to_excel(writer, sheet_name='Sheet2')

            # Close the Pandas Excel writer and output the Excel file.
            writer.save()
            print(writer)

        else:
            date1 = (self.label1.text())
            date2 = (self.label2.text())

            format_date1 = "%Y-%m-%d"
            out_date1 = datetime.strptime(date1, format_date1)
            print(out_date1)

            format_date2 = "%Y-%m-%d"
            out_date2 = datetime.strptime(date2, format_date2)
            print(out_date2)

            df = pd.read_sql_query(
                "SELECT * FROM PatientsServices WHERE WorkId='%s' and date BETWEEN '%s' AND '%s'"
                % (self.searchLE1.text(), out_date1, out_date2), db)
            # df.to_excel('output.xlsx')

            # Create a Pandas Excel writer using XlsxWriter as the engine.
            writer = pd.ExcelWriter('pandas_simple.xlsx', engine='xlsxwriter')

            # Convert the dataframe to an XlsxWriter Excel object.
            df.to_excel(writer, sheet_name='Sheet2')

            # Close the Pandas Excel writer and output the Excel file.
            writer.save()
            print(writer)

    def onExport_btnSubscribers(self):
        db = sqlite3.connect("/home/eamon/Desktop/test.sqlite")

        df1 = pd.read_sql_query("SELECT * FROM Subscribers ", db)
        # df.to_excel('output.xlsx')

        # Create a Pandas Excel writer using XlsxWriter as the engine.
        writer = pd.ExcelWriter('السقف.xlsx', engine='xlsxwriter')

        # Convert the dataframe to an XlsxWriter Excel object.
        df1.to_excel(writer, sheet_name='Subscribers1')

        # Close the Pandas Excel writer and output the Excel file.
        writer.save()

        print(writer)
Пример #18
0
class VOGView(AbstractView):
    def __init__(self,
                 name: str = "VOG_NONE",
                 log_handlers: [StreamHandler] = None):
        self._logger = getLogger(__name__)
        if log_handlers:
            for h in log_handlers:
                self._logger.addHandler(h)
        self._logger.debug("Initializing")
        super().__init__(name)
        """ Min size for the VOG window """
        self._subwindow_height = 222
        self._subwindow_width = 518
        """ min and max sizes for the configuration popup (width, height) """
        self._popup_min = (229, 409)
        self._popup_max = (300, 409)
        """ Set configuration value display area"""
        self._config_frame = EasyFrame()
        self._config_vertical_layout = QVBoxLayout(self._config_frame)
        self._config_label = QLabel(self._config_frame)
        self._config_label.setAlignment(Qt.AlignCenter)
        self._config_val_line_edit = QLineEdit(self._config_frame)
        self._config_val_line_edit.setAlignment(Qt.AlignCenter)

        self._config_vertical_layout.addWidget(self._config_label)
        self._config_vertical_layout.addWidget(self._config_val_line_edit)
        """ Set preset button selection area. """
        self._nhtsa_button = ClickAnimationButton()
        self._eblindfold_button = ClickAnimationButton()
        self._direct_control_button = ClickAnimationButton()
        """ Set open duration, close duration, and debounce time settings display area. """
        self._input_box_frame = EasyFrame()
        self._input_box_grid_layout = QGridLayout(self._input_box_frame)
        self._input_box_grid_layout.setContentsMargins(0, 6, 0, 6)

        self._open_dur_label = QLabel(self._input_box_frame)
        self._open_dur_line_edit = QLineEdit(self._input_box_frame)
        self._open_dur_line_edit.setFixedWidth(80)
        self._open_inf_check_box = QCheckBox(self._input_box_frame)

        self._close_dur_label = QLabel(self._input_box_frame)
        self._close_dur_line_edit = QLineEdit(self._input_box_frame)
        self._close_dur_line_edit.setFixedWidth(80)
        self._close_inf_check_box = QCheckBox(self._input_box_frame)

        self._debounce_label = QLabel(self._input_box_frame)
        self._debounce_time_line_edit = QLineEdit(self._input_box_frame)
        self._debounce_time_line_edit.setFixedWidth(80)

        self._input_box_grid_layout.addWidget(self._open_dur_label, 0, 0, 1, 1)
        self._input_box_grid_layout.addWidget(self._open_dur_line_edit, 0, 1,
                                              1, 1)
        self._input_box_grid_layout.addWidget(self._open_inf_check_box, 0, 2,
                                              1, 1)
        self._input_box_grid_layout.addWidget(self._close_dur_label, 1, 0, 1,
                                              1)
        self._input_box_grid_layout.addWidget(self._close_dur_line_edit, 1, 1,
                                              1, 1)
        self._input_box_grid_layout.addWidget(self._close_inf_check_box, 1, 2,
                                              1, 1)
        self._input_box_grid_layout.addWidget(self._debounce_label, 2, 0, 1, 1)
        self._input_box_grid_layout.addWidget(self._debounce_time_line_edit, 2,
                                              1, 1, 1)
        """ Set button mode setting display area. """
        self._button_mode_frame = EasyFrame()
        self._button_mode_horiz_layout = QGridLayout(self._button_mode_frame)
        self._button_mode_horiz_layout.setContentsMargins(0, 6, 0, 6)
        self._button_mode_label = QLabel(self._button_mode_frame)
        self._button_mode_selector = QComboBox(self._button_mode_frame)

        self._button_mode_selector.addItem("")
        self._button_mode_selector.addItem("")

        self._button_mode_horiz_layout.addWidget(self._button_mode_label, 0, 0,
                                                 1, 1)
        self._button_mode_horiz_layout.addWidget(self._button_mode_selector, 0,
                                                 1, 1, 1)
        """ Set control mode setting display area. """
        self._control_mode_label = QLabel(self._button_mode_frame)
        self._control_mode_selector = QComboBox(self._button_mode_frame)

        self._control_mode_selector.addItem("")
        self._control_mode_selector.addItem("")

        self._button_mode_horiz_layout.addWidget(self._control_mode_label, 1,
                                                 0, 1, 1)
        self._button_mode_horiz_layout.addWidget(self._control_mode_selector,
                                                 1, 1, 1, 1)
        """ Set upload button selection area. """
        self._upload_settings_button = ClickAnimationButton()
        """ Set manual control selection area. """
        self._manual_control_button_frame = EasyFrame()
        self._manual_control_button_layout = QHBoxLayout(
            self._manual_control_button_frame)

        self._manual_control_open_button = ClickAnimationButton()
        self._manual_control_close_button = ClickAnimationButton()

        self._manual_control_button_layout.addWidget(
            self._manual_control_open_button)
        self._manual_control_button_layout.addWidget(
            self._manual_control_close_button)
        self._manual_control_button_layout.setMargin(0)
        """ device settings display """
        self._dev_sets_frame = EasyFrame()

        self._dev_sets_layout = QVBoxLayout(self._dev_sets_frame)

        self.config_button = ClickAnimationButton()
        self.config_button.clicked.connect(self._config_button_handler)

        self._config_win = ConfigPopUp()
        self._config_win.setMinimumSize(self._popup_min[0], self._popup_min[1])
        self._config_win.setMaximumSize(self._popup_max[0], self._popup_max[1])
        self._config_win.setLayout(self._dev_sets_layout)
        """ Add widgets to layout. """
        self._dev_sets_layout.addWidget(self._config_frame)
        self._dev_sets_layout.addWidget(self._input_box_frame)
        self._dev_sets_layout.addWidget(self._button_mode_frame)
        self._dev_sets_layout.addWidget(self._nhtsa_button)
        self._dev_sets_layout.addWidget(self._eblindfold_button)
        self._dev_sets_layout.addWidget(self._direct_control_button)
        self._dev_sets_layout.addWidget(self._upload_settings_button)

        self.layout().addWidget(self.config_button, 0, 0,
                                Qt.AlignTop | Qt.AlignRight)
        self.config_button.setFixedSize(30, 25)

        self.layout().addWidget(self._manual_control_button_frame, 0, 0,
                                Qt.AlignBottom | Qt.AlignLeft)
        self._manual_control_open_button.setFixedSize(70, 25)
        self._manual_control_close_button.setFixedSize(70, 25)

        self.layout().setMargin(0)

        self._strings = dict()
        self._lang_enum = LangEnum.ENG
        self.setMinimumSize(self._subwindow_width, self._subwindow_height)
        self.resize(self._subwindow_width, self._subwindow_height)
        self._logger.debug("Initialized")

    def add_graph(self, graph) -> None:
        """
        Add Graph to view.
        :return None:
        """
        self._logger.debug("running")
        self.layout().addWidget(graph, 0, 0)
        self.config_button.raise_()
        self._manual_control_button_frame.raise_()
        self._logger.debug("done")

    def _config_button_handler(self) -> None:
        """
        handles the config button
        :return None:
        """
        self._logger.debug("running")
        self._config_win.exec_()
        self._logger.debug("done")

    def set_config_val_line_edit_handler(self, func: classmethod) -> None:
        """
        Sets the config val line handler.
        :param func: classmethod that handles the config val line.
        :return None:
        """
        self._logger.debug("running")
        self._config_val_line_edit.textChanged.connect(func)
        self._logger.debug("done")

    def set_nhtsa_button_handler(self, func: classmethod) -> None:
        """
        Sets NHTSA button press handler.
        :param func: classmethod that handles the NHTSA button.
        :return None:
        """
        self._logger.debug("running")
        self._nhtsa_button.clicked.connect(func)
        self._logger.debug("done")

    def set_eblindfold_button_handler(self, func: classmethod) -> None:
        """
        Sets eBlindfold button press handler.
        :param func: classmethod that handles the eBlindfold button.
        :return None:
        """
        self._logger.debug("running")
        self._eblindfold_button.clicked.connect(func)
        self._logger.debug("done")

    def set_direct_control_button_handler(self, func: classmethod) -> None:
        """
        Sets Direct Control button press handler.
        :param func: classmethod that handles the Direct Control button.
        :return None:
        """
        self._logger.debug("running")
        self._direct_control_button.clicked.connect(func)
        self._logger.debug("done")

    def set_open_dur_line_edit_handler(self, func: classmethod) -> None:
        """
        Sets open duration line edit handler.
        :param func: classmethod that handles the line edit.
        :return None:
        """
        self._logger.debug("running")
        self._open_dur_line_edit.textChanged.connect(func)
        self._logger.debug("done")

    def set_close_dur_line_edit_handler(self, func: classmethod) -> None:
        """
        Sets close duration line edit handler.
        :param func: classmethod that handles the line edit.
        :return None:
        """
        self._logger.debug("running")
        self._close_dur_line_edit.textChanged.connect(func)
        self._logger.debug("done")

    def set_open_inf_check_box_handler(self, func: classmethod) -> None:
        """
        Sets open INF checkbox handler.
        :param func: classmethod that handles the checkbox, requires bool param.
        :return None:
        """
        self._logger.debug("running")
        self._open_inf_check_box.stateChanged.connect(func)
        self._logger.debug("done")

    def set_close_inf_check_box_handler(self, func: classmethod) -> None:
        """
        Sets close INF checkbox handler.
        :param func: classmethod that handles the checkbox, requires bool param.
        :return None:
        """
        self._logger.debug("running")
        self._close_inf_check_box.stateChanged.connect(func)
        self._logger.debug("done")

    def set_debounce_time_line_edit_handler(self, func: classmethod) -> None:
        """
        Sets debounce time line edit handler.
        :param func: classmethod that handles the line edit.
        :return None:
        """
        self._logger.debug("running")
        self._debounce_time_line_edit.textChanged.connect(func)
        self._logger.debug("done")

    def set_button_mode_selector_handler(self, func: classmethod) -> None:
        """
        Sets button mode combo box handler.
        :param func: classmethod that handles the combo.
        :return None:
        """
        self._logger.debug("running")
        self._button_mode_selector.currentIndexChanged.connect(func)
        self._logger.debug("done")

    def set_control_mode_selector_handler(self, func: classmethod) -> None:
        """
        Sets button mode combo box handler.
        :param func: classmethod that handles the combo.
        :return None:
        """
        self._logger.debug("running")
        self._control_mode_selector.currentIndexChanged.connect(func)
        self._logger.debug("done")

    def set_upload_settings_button_handler(self, func: classmethod) -> None:
        """
        Sets upload settings button handler.
        :param func: classmethod that handles the button.
        :return None:
        """
        self._logger.debug("running")
        self._upload_settings_button.clicked.connect(func)
        self._logger.debug("done")

    def set_manual_control_open_button_handler(self,
                                               func: classmethod) -> None:
        """
        Sets manual open button handler.
        :param func: classmethod that handles the button.
        :return None:
        """
        self._logger.debug("running")
        self._manual_control_open_button.clicked.connect(func)
        self._logger.debug("done")

    def set_manual_control_close_button_handler(self,
                                                func: classmethod) -> None:
        """
        Sets manual close button handler.
        :param func: classmethod that handles the button.
        :return None:
        """
        self._logger.debug("running")
        self._manual_control_close_button.clicked.connect(func)
        self._logger.debug("done")

    @property
    def config_text(self) -> str:
        """
        Get the string value found in the config text box.
        :return str: string value in the text box.
        """
        return self._config_val_line_edit.text()

    @config_text.setter
    def config_text(self, val: str) -> None:
        """
        Set the string value found in the config text box.
        :param val: string value to set the config text box.
        :return None:
        """
        self._logger.debug("running")
        self._config_val_line_edit.setText(val)
        self._logger.debug("done")

    @property
    def open_duration(self) -> str:
        """
        Get the string value found in the open duration text box.
        :return str: string value in the text box.
        """
        return self._open_dur_line_edit.text()

    @open_duration.setter
    def open_duration(self, val: str) -> None:
        """
        Set the string value found in the open duration text box.
        :param val: string value to set the open duration text box.
        :return None:
        """
        self._logger.debug("running")
        self._open_dur_line_edit.setText(val)
        self._logger.debug("done")

    @property
    def close_duration(self) -> str:
        """
        Get the string value found in the close duration text box.
        :return str: string value in the text box.
        """
        return self._close_dur_line_edit.text()

    @close_duration.setter
    def close_duration(self, val: str) -> None:
        """
        Set the string value found in the close duration text box.
        :param val: string value to set the close duration text box.
        :return None:
        """
        self._logger.debug("running")
        self._close_dur_line_edit.setText(val)
        self._logger.debug("done")

    @property
    def debounce_val(self) -> str:
        """
        Get the string value found in the debounce time text box.
        :return str: string value in the text box.
        """
        return self._debounce_time_line_edit.text()

    @debounce_val.setter
    def debounce_val(self, val: str) -> None:
        """
        Set the string value found in the debounce time text box.
        :param val: string value to set the debounce text box.
        :return None:
        """
        self._logger.debug("running")
        self._debounce_time_line_edit.setText(val)
        self._logger.debug("done")

    @property
    def open_inf_check_box(self) -> bool:
        """
        Get the check box state.
        :return bool: returns true if the box is checked.
        """
        return self._open_inf_check_box.isChecked()

    @open_inf_check_box.setter
    def open_inf_check_box(self, val: bool) -> None:
        """
        Set the check box state.
        :param val: bool value to set the check box.
        :return None:
        """
        self._logger.debug("running")
        self._open_inf_check_box.setChecked(val)
        self._logger.debug("done")

    @property
    def close_inf_check_box(self) -> bool:
        """
        Get the check box state.
        :return bool: returns true if the box is checked.
        """
        return self._close_inf_check_box.isChecked()

    @close_inf_check_box.setter
    def close_inf_check_box(self, val: bool) -> None:
        """
        Set the check box state.
        :param val: bool value to set the check box.
        :return None:
        """
        self._logger.debug("running")
        self._close_inf_check_box.setChecked(val)
        self._logger.debug("done")

    @property
    def button_mode(self) -> int:
        """
        Get index of button mode.
        :return int: index of current button mode.
        """
        return self._button_mode_selector.currentIndex()

    @button_mode.setter
    def button_mode(self, val: int) -> None:
        """
        Set index of button mode.
        :return None:
        """
        self._logger.debug("running")
        self._button_mode_selector.setCurrentIndex(val)
        self._logger.debug("done")

    @property
    def control_mode(self) -> int:
        """
        Get index of button mode.
        :return int: index of current button mode.
        """
        return self._control_mode_selector.currentIndex()

    @control_mode.setter
    def control_mode(self, val: int) -> None:
        """
        Set index of button mode.
        :return None:
        """
        self._logger.debug("running")
        self._control_mode_selector.setCurrentIndex(val)
        self._logger.debug("done")

    def set_open_dur_err(self, err: bool) -> None:
        """
        Set this text entry to error style depending on err.
        :param err: If this text entry needs to be error styel
        :return None:
        """
        self._logger.debug("running")
        if err:
            self._open_dur_line_edit.setStyleSheet(tab_line_edit_error_style)
        else:
            self._open_dur_line_edit.setStyleSheet(
                tab_line_edit_compliant_style)
        self._logger.debug("done")

    def set_close_dur_err(self, err: bool) -> None:
        """
        Set this text entry to error style depending on err.
        :param err: If this text entry needs to be error styel
        :return None:
        """
        self._logger.debug("running")
        if err:
            self._close_dur_line_edit.setStyleSheet(tab_line_edit_error_style)
        else:
            self._close_dur_line_edit.setStyleSheet(
                tab_line_edit_compliant_style)
        self._logger.debug("done")

    def set_debounce_err(self, err: bool) -> None:
        """
        Set this text entry to error style depending on err.
        :param err: If this text entry needs to be error styel
        :return None:
        """
        self._logger.debug("running")
        if err:
            self._debounce_time_line_edit.setStyleSheet(
                tab_line_edit_error_style)
        else:
            self._debounce_time_line_edit.setStyleSheet(
                tab_line_edit_compliant_style)
        self._logger.debug("done")

    @property
    def language(self) -> LangEnum:
        """
        Get the current language setting
        :return LangEnum: The current language enumerator being used
        """
        return self._lang_enum

    @language.setter
    def language(self, lang: LangEnum) -> None:
        """
        Set the language for this view object and reload the text and tooltips.
        :param lang: the language to use.
        :return None:
        """
        self._logger.debug("running")
        self._strings = strings[lang]
        self._set_texts()
        self._set_tooltips()
        self._logger.debug("done")

    def set_upload_button(self, is_active: bool) -> None:
        """
        Set upload button activity to is_active.
        :param is_active: Whether this button should be active.
        :return None:
        """
        self._logger.debug("running")
        self._upload_settings_button.setEnabled(is_active)
        self._logger.debug("done")

    def _set_texts(self) -> None:
        """
        Set text fields of view object.
        :return None:
        """
        self._logger.debug("running")
        self._config_label.setText(self._strings[StringsEnum.CONFIG_LABEL])
        self._config_val_line_edit.setText(
            self._strings[StringsEnum.CONFIG_LABEL])
        self._nhtsa_button.setText(self._strings[StringsEnum.NHTSA_LABEL])
        self._eblindfold_button.setText(
            self._strings[StringsEnum.EBLIND_LABEL])
        self._direct_control_button.setText(
            self._strings[StringsEnum.DCON_LABEL])
        self._open_dur_label.setText(
            self._strings[StringsEnum.OPEN_DURATION_LABEL])
        self._open_inf_check_box.setText(self._strings[StringsEnum.INF_LABEL])
        self._close_dur_label.setText(
            self._strings[StringsEnum.CLOSE_DURATION_LABEL])
        self._close_inf_check_box.setText(self._strings[StringsEnum.INF_LABEL])
        self._debounce_label.setText(self._strings[StringsEnum.DEBOUNCE_LABEL])
        self._button_mode_label.setText(
            self._strings[StringsEnum.BUTTON_MODE_LABEL])
        self._button_mode_selector.setItemText(
            0, self._strings[StringsEnum.HOLD_VAL_LABEL])
        self._button_mode_selector.setItemText(
            1, self._strings[StringsEnum.CLICK_VAL_LABEL])
        self._control_mode_label.setText(
            self._strings[StringsEnum.CONTROL_MODE_LABEL])
        self._control_mode_selector.setItemText(
            0, self._strings[StringsEnum.LENS_VAL_LABEL])
        self._control_mode_selector.setItemText(
            1, self._strings[StringsEnum.TRIAL_VAL_LABEL])
        self._upload_settings_button.setText(
            self._strings[StringsEnum.UPLOAD_BUTTON_LABEL])
        self._manual_control_open_button.setText(
            self._strings[StringsEnum.MANUAL_OPEN_LABEL])
        self._manual_control_close_button.setText(
            self._strings[StringsEnum.MANUAL_CLOSE_LABEL])
        self.config_button.setText(self._strings[StringsEnum.CONFIG_TAB_LABEL])
        self.config_button.setText("...")
        self._config_win.setWindowTitle(
            self.get_name() + " " +
            self._strings[StringsEnum.CONFIG_TAB_LABEL])
        self._logger.debug("done")

    def _set_tooltips(self) -> None:
        """
        Set tooltip text fields of view object.
        :return None:
        """
        self._logger.debug("running")
        self._config_label.setToolTip(
            self._strings[StringsEnum.CONFIG_LABEL_TOOLTIP])
        self._config_val_line_edit.setToolTip(
            self._strings[StringsEnum.CONFIG_LABEL_TOOLTIP])
        self._open_dur_label.setToolTip(
            self._strings[StringsEnum.OPEN_DURATION_TOOLTIP])
        self._close_dur_label.setToolTip(
            self._strings[StringsEnum.CLOSE_DURATION_TOOLTIP])
        self._debounce_label.setToolTip(
            self._strings[StringsEnum.DEBOUNCE_TOOLTIP])
        self._button_mode_label.setToolTip(
            self._strings[StringsEnum.BUTTON_MODE_TOOLTIP])
        self._control_mode_label.setToolTip(
            self._strings[StringsEnum.CONTROL_MODE_TOOLTIP])
        self._upload_settings_button.setToolTip(
            self._strings[StringsEnum.UPLOAD_BUTTON_TOOLTIP])
        self._manual_control_open_button.setToolTip(
            self._strings[StringsEnum.MANUAL_OPEN_TOOLTIP])
        self._manual_control_close_button.setToolTip(
            self._strings[StringsEnum.MANUAL_CLOSE_TOOLTIP])
        self.config_button.setToolTip(
            self._strings[StringsEnum.CONFIG_TAB_TOOLTIP])
        self._logger.debug("done")
Пример #19
0
class MixedDistributionChart(QDialog):
    def __init__(self, parent=None, show_mode=True, toolbar=False, use_animation=False):
        flags = Qt.Window | Qt.WindowTitleHint | Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint
        super().__init__(parent=parent, f=flags)
        self.setWindowTitle(self.tr("Mixed Distribution Chart"))
        self.figure = plt.figure(figsize=(4, 3))
        self.axes = self.figure.subplots()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.main_layout = QGridLayout(self)
        self.main_layout.addWidget(self.toolbar, 0, 0, 1, 2)
        self.main_layout.addWidget(self.canvas, 1, 0, 1, 2)
        if not toolbar:
            self.toolbar.hide()
        self.supported_scales = [("log-linear", self.tr("Log-linear")),
                                 ("log", self.tr("Log")),
                                 ("phi", self.tr("φ")),
                                 ("linear", self.tr("Linear"))]

        self.scale_label = QLabel(self.tr("Scale"))
        self.scale_combo_box = QComboBox()
        self.scale_combo_box.addItems([name for key, name in self.supported_scales])
        self.scale_combo_box.currentIndexChanged.connect(self.update_chart)
        self.main_layout.addWidget(self.scale_label, 2, 0)
        self.main_layout.addWidget(self.scale_combo_box, 2, 1)
        self.interval_label = QLabel(self.tr("Interval [ms]"))
        self.interval_input = QSpinBox()
        self.interval_input.setRange(0, 10000)
        self.interval_input.setValue(30)
        self.interval_input.valueChanged.connect(self.update_animation)
        self.main_layout.addWidget(self.interval_label, 3, 0)
        self.main_layout.addWidget(self.interval_input, 3, 1)
        self.repeat_check_box = QCheckBox(self.tr("Repeat"))
        self.repeat_check_box.setChecked(False)
        self.repeat_check_box.stateChanged.connect(self.update_animation)
        self.save_button = QPushButton(self.tr("Save"))
        self.save_button.clicked.connect(self.save_animation)
        self.main_layout.addWidget(self.repeat_check_box, 4, 0)
        self.main_layout.addWidget(self.save_button, 4, 1)
        self.show_mode = show_mode
        self.animation = None
        self.last_model = None
        self.last_result = None

        if not use_animation:
            self.interval_label.setVisible(False)
            self.interval_input.setVisible(False)
            self.repeat_check_box.setVisible(False)
            self.save_button.setVisible(False)

        self.normal_msg = QMessageBox(parent=self)
        self.file_dialog = QFileDialog(parent=self)

    @property
    def scale(self) -> str:
        index = self.scale_combo_box.currentIndex()
        key, name = self.supported_scales[index]
        return key

    @property
    def transfer(self) -> typing.Callable:
        if self.scale == "log-linear":
            return lambda classes_φ: convert_φ_to_μm(classes_φ)
        elif self.scale == "log":
            return lambda classes_φ: np.log(convert_φ_to_μm(classes_φ))
        elif self.scale == "phi":
            return lambda classes_φ: classes_φ
        elif self.scale == "linear":
            return lambda classes_φ: convert_φ_to_μm(classes_φ)

    @property
    def xlabel(self) -> str:
        if self.scale == "log-linear":
            return self.tr("Grain-size [μm]")
        elif self.scale == "log":
            return self.tr("Ln(grain-size in μm)")
        elif self.scale == "phi":
            return self.tr("Grain-size [φ]")
        elif self.scale == "linear":
            return self.tr("Grain-size [μm]")

    @property
    def ylabel(self) -> str:
        return self.tr("Frequency")

    @property
    def xlog(self) -> bool:
        if self.scale == "log-linear":
            return True
        else:
            return False

    @property
    def interval(self) -> float:
        return self.interval_input.value()

    @property
    def repeat(self) -> bool:
        return self.repeat_check_box.isChecked()

    def show_demo(self):
        demo_model = get_demo_view_model()
        self.show_model(demo_model)

    def update_chart(self):
        if self.last_model is not None:
            self.show_model(self.last_model)
        elif self.last_result is not None:
            self.show_result(self.last_result)

    def update_animation(self):
        if self.last_result is not None:
            self.show_result(self.last_result)

    def show_model(self, model: SSUViewModel, quick=False):
        if self.animation is not None:
            self.animation._stop()
            self.animation = None
        if not quick:
            self.last_result = None

            self.last_model = model
            self.interval_label.setEnabled(False)
            self.interval_input.setEnabled(False)
            self.repeat_check_box.setEnabled(False)
            self.save_button.setEnabled(False)

            self.axes.clear()
            x = self.transfer(model.classes_φ)
            if self.xlog:
                self.axes.set_xscale("log")
            self.axes.set_title(model.title)
            self.axes.set_xlabel(self.xlabel)
            self.axes.set_ylabel(self.ylabel)
            self.target = self.axes.plot(x, model.target, c="#ffffff00", marker=".", ms=8, mfc="black", mew=0.0, label=self.tr("Target"))[0]
            # scatter can not be modified from the tool bar
            # self.target = self.axes.scatter(x, model.target, c="black", s=1)
            self.axes.set_xlim(x[0], x[-1])
            self.axes.set_ylim(0.0, round(np.max(model.target)*1.2, 2))
            self.mixed = self.axes.plot(x, model.mixed, c="black", label=self.tr("Mixed"))[0]
            self.components = [self.axes.plot(x, distribution*fraction, c=plt.get_cmap()(i), label=model.component_prefix+str(i+1))[0] for i, (distribution, fraction) in enumerate(zip(model.distributions, model.fractions))]
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                colors = [plt.get_cmap()(i) for i in range(model.n_components)]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            if model.n_components < 6:
                self.axes.legend(loc="upper left")
            self.figure.tight_layout()
            self.canvas.draw()
        else:
            self.mixed.set_ydata(model.mixed)
            for comp, distribution, fraction in zip(self.components, model.distributions, model.fractions):
                comp.set_ydata(distribution*fraction)
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines.set_offsets(modes)
            self.canvas.draw()

    def show_result(self, result: SSUResult):
        if self.animation is not None:
            self.animation._stop()
            self.animation = None
        self.last_model = None
        self.last_result = result
        self.interval_label.setEnabled(True)
        self.interval_input.setEnabled(True)
        self.repeat_check_box.setEnabled(True)
        self.save_button.setEnabled(True)

        models = iter(result.view_models)
        first = next(models)
        x = self.transfer(first.classes_φ)
        self.axes.cla()
        if self.xlog:
            self.axes.set_xscale("log")
        self.axes.set_title(first.title)
        self.axes.set_xlabel(self.xlabel)
        self.axes.set_ylabel(self.ylabel)
        self.target = self.axes.plot(x, first.target, c="#ffffff00", marker=".", ms=8, mfc="black", mew=0.0)[0]
        self.axes.set_xlim(x[0], x[-1])
        self.axes.set_ylim(0.0, round(np.max(first.target)*1.2, 2))
        self.figure.tight_layout()
        # self.canvas.draw()
        colors = [plt.get_cmap()(i) for i in range(first.n_components)]
        def init():
            model = first
            self.mixed = self.axes.plot(x, model.mixed, c="black")[0]
            self.components = [self.axes.plot(x, distribution*fraction, c=plt.get_cmap()(i))[0] for i, (distribution, fraction) in enumerate(zip(model.distributions, model.fractions))]
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            return self.mixed, self.vlines, *self.components
        def animate(current):
            model = current
            self.mixed.set_ydata(current.mixed)
            for line, distribution, fraction in zip(self.components, model.distributions, model.fractions):
                line.set_ydata(distribution*fraction)
            if self.show_mode:
                self.vlines.remove()
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            return self.mixed, self.vlines, *self.components
        self.animation = FuncAnimation(self.figure, animate, frames=models, init_func=init,
                                       interval=self.interval, blit=True,
                                       repeat=self.repeat, repeat_delay=3.0, save_count=result.n_iterations)

    def save_animation(self):
        if self.last_result is not None:
            filename, format_str = self.file_dialog.getSaveFileName(self, self.tr("Save the animation of this SSU result"), None, self.tr("MPEG-4 Video File (*.mp4);;Graphics Interchange Format (*.gif)"))
            if filename is None or filename == "":
                return
            progress = QProgressDialog(self)
            progress.setRange(0, 100)
            progress.setLabelText(self.tr("Saving Animation [{0} Frames]").format(self.last_result.n_iterations))
            canceled = False
            def save_callback(i, n):
                if progress.wasCanceled():
                    nonlocal canceled
                    canceled = True
                    raise StopIteration()
                progress.setValue((i+1)/n*100)
                QCoreApplication.processEvents()
            self.show_result(self.last_result)
            # plt.rcParams["savefig.dpi"] = 120.0
            if "*.gif" in format_str:
                if not ImageMagickWriter.isAvailable():
                    self.normal_msg.setWindowTitle(self.tr("Error"))
                    self.normal_msg.setText(self.tr("ImageMagick is not installed, please download and install it from its offical website (https://imagemagick.org/index.php)."))
                    self.normal_msg.exec_()
                else:
                    self.animation.save(filename, writer="imagemagick", fps=30, progress_callback=save_callback)
            elif "*.mp4" in format_str:
                if not FFMpegWriter.isAvailable():
                    self.normal_msg.setWindowTitle(self.tr("Error"))
                    self.normal_msg.setText(self.tr("FFMpeg is not installed, please download and install it from its offical website (https://ffmpeg.org/)."))
                    self.normal_msg.exec_()
                else:
                    self.animation.save(filename, writer="ffmpeg", fps=30, progress_callback=save_callback)
            # plt.rcParams["savefig.dpi"] = 300.0
            if not canceled:
                progress.setValue(100)
Пример #20
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.renderArea = RenderArea()

        self.shapeComboBox = QComboBox()
        self.shapeComboBox.addItem("Polygon", RenderArea.Polygon)
        self.shapeComboBox.addItem("Rectangle", RenderArea.Rect)
        self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect)
        self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse)
        self.shapeComboBox.addItem("Pie", RenderArea.Pie)
        self.shapeComboBox.addItem("Chord", RenderArea.Chord)
        self.shapeComboBox.addItem("Path", RenderArea.Path)
        self.shapeComboBox.addItem("Line", RenderArea.Line)
        self.shapeComboBox.addItem("Polyline", RenderArea.Polyline)
        self.shapeComboBox.addItem("Arc", RenderArea.Arc)
        self.shapeComboBox.addItem("Points", RenderArea.Points)
        self.shapeComboBox.addItem("Text", RenderArea.Text)
        self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap)

        shapeLabel = QLabel("&Shape:")
        shapeLabel.setBuddy(self.shapeComboBox)

        self.penWidthSpinBox = QSpinBox()
        self.penWidthSpinBox.setRange(0, 20)
        self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)")

        penWidthLabel = QLabel("Pen &Width:")
        penWidthLabel.setBuddy(self.penWidthSpinBox)

        self.penStyleComboBox = QComboBox()
        self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
        self.penStyleComboBox.addItem("Dash", Qt.DashLine)
        self.penStyleComboBox.addItem("Dot", Qt.DotLine)
        self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine)
        self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine)
        self.penStyleComboBox.addItem("None", Qt.NoPen)

        penStyleLabel = QLabel("&Pen Style:")
        penStyleLabel.setBuddy(self.penStyleComboBox)

        self.penCapComboBox = QComboBox()
        self.penCapComboBox.addItem("Flat", Qt.FlatCap)
        self.penCapComboBox.addItem("Square", Qt.SquareCap)
        self.penCapComboBox.addItem("Round", Qt.RoundCap)

        penCapLabel = QLabel("Pen &Cap:")
        penCapLabel.setBuddy(self.penCapComboBox)

        self.penJoinComboBox = QComboBox()
        self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
        self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin)
        self.penJoinComboBox.addItem("Round", Qt.RoundJoin)

        penJoinLabel = QLabel("Pen &Join:")
        penJoinLabel.setBuddy(self.penJoinComboBox)

        self.brushStyleComboBox = QComboBox()
        self.brushStyleComboBox.addItem("Linear Gradient",
                Qt.LinearGradientPattern)
        self.brushStyleComboBox.addItem("Radial Gradient",
                Qt.RadialGradientPattern)
        self.brushStyleComboBox.addItem("Conical Gradient",
                Qt.ConicalGradientPattern)
        self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern)
        self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern)
        self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern)
        self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern)
        self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern)
        self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern)
        self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern)
        self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern)
        self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern)
        self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern)
        self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern)
        self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern)
        self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern)
        self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern)
        self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern)
        self.brushStyleComboBox.addItem("None", Qt.NoBrush)

        brushStyleLabel = QLabel("&Brush Style:")
        brushStyleLabel.setBuddy(self.brushStyleComboBox)

        otherOptionsLabel = QLabel("Other Options:")
        self.antialiasingCheckBox = QCheckBox("&Antialiasing")
        self.transformationsCheckBox = QCheckBox("&Transformations")

        self.shapeComboBox.activated.connect(self.shapeChanged)
        self.penWidthSpinBox.valueChanged.connect(self.penChanged)
        self.penStyleComboBox.activated.connect(self.penChanged)
        self.penCapComboBox.activated.connect(self.penChanged)
        self.penJoinComboBox.activated.connect(self.penChanged)
        self.brushStyleComboBox.activated.connect(self.brushChanged)
        self.antialiasingCheckBox.toggled.connect(self.renderArea.setAntialiased)
        self.transformationsCheckBox.toggled.connect(self.renderArea.setTransformed)

        mainLayout = QGridLayout()
        mainLayout.setColumnStretch(0, 1)
        mainLayout.setColumnStretch(3, 1)
        mainLayout.addWidget(self.renderArea, 0, 0, 1, 4)
        mainLayout.setRowMinimumHeight(1, 6)
        mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight)
        mainLayout.addWidget(self.shapeComboBox, 2, 2)
        mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penWidthSpinBox, 3, 2)
        mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penStyleComboBox, 4, 2)
        mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penCapComboBox, 5, 2)
        mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penJoinComboBox, 6, 2)
        mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight)
        mainLayout.addWidget(self.brushStyleComboBox, 7, 2)
        mainLayout.setRowMinimumHeight(8, 6)
        mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight)
        mainLayout.addWidget(self.antialiasingCheckBox, 9, 2)
        mainLayout.addWidget(self.transformationsCheckBox, 10, 2)
        self.setLayout(mainLayout)

        self.shapeChanged()
        self.penChanged()
        self.brushChanged()
        self.antialiasingCheckBox.setChecked(True)

        self.setWindowTitle("Basic Drawing")

    def shapeChanged(self):
        shape = self.shapeComboBox.itemData(self.shapeComboBox.currentIndex(),
                IdRole)
        self.renderArea.setShape(shape)

    def penChanged(self):
        width = self.penWidthSpinBox.value()
        style = Qt.PenStyle(self.penStyleComboBox.itemData(
                self.penStyleComboBox.currentIndex(), IdRole))
        cap = Qt.PenCapStyle(self.penCapComboBox.itemData(
                self.penCapComboBox.currentIndex(), IdRole))
        join = Qt.PenJoinStyle(self.penJoinComboBox.itemData(
                self.penJoinComboBox.currentIndex(), IdRole))

        self.renderArea.setPen(QPen(Qt.blue, width, style, cap, join))

    def brushChanged(self):
        style = Qt.BrushStyle(self.brushStyleComboBox.itemData(
                self.brushStyleComboBox.currentIndex(), IdRole))

        if style == Qt.LinearGradientPattern:
            linearGradient = QLinearGradient(0, 0, 100, 100)
            linearGradient.setColorAt(0.0, Qt.white)
            linearGradient.setColorAt(0.2, Qt.green)
            linearGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(linearGradient))
        elif style == Qt.RadialGradientPattern:
            radialGradient = QRadialGradient(50, 50, 50, 70, 70)
            radialGradient.setColorAt(0.0, Qt.white)
            radialGradient.setColorAt(0.2, Qt.green)
            radialGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(radialGradient))
        elif style == Qt.ConicalGradientPattern:
            conicalGradient = QConicalGradient(50, 50, 150)
            conicalGradient.setColorAt(0.0, Qt.white)
            conicalGradient.setColorAt(0.2, Qt.green)
            conicalGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(conicalGradient))
        elif style == Qt.TexturePattern:
            self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
        else:
            self.renderArea.setBrush(QBrush(Qt.green, style))
Пример #21
0
class JumpEditor(CustomDialog):
    def __init__(self, parent: Optional[QWidget], jump: Jump):
        super(JumpEditor, self).__init__(parent, "Jump Editor")

        self.jump = jump

        self.screen_spinner = Spinner(parent=self,
                                      maximum=MAX_SCREEN_INDEX,
                                      base=10)

        position_layout = QFormLayout()
        position_layout.addRow("Jump on screen:", self.screen_spinner)

        level_group_box = QGroupBox("Level position")
        level_group_box.setLayout(position_layout)

        self.exit_action = QComboBox(self)
        self.exit_action.addItems(JUMP_ACTIONS)

        self.exit_horizontal = Spinner(parent=self,
                                       maximum=MAX_HORIZ_POSITION,
                                       base=10)

        self.exit_vertical = QComboBox(self)
        self.exit_vertical.addItems(VERT_POSITIONS)

        exit_layout = QFormLayout()
        exit_layout.addRow("Exit action:", self.exit_action)
        exit_layout.addRow("Exit position x:", self.exit_horizontal)
        exit_layout.addRow("Exit position y:", self.exit_vertical)

        exit_group_box = QGroupBox("Exit options")
        exit_group_box.setLayout(exit_layout)

        button_box = QDialogButtonBox()
        self.ok_button = button_box.addButton(QDialogButtonBox.Ok)
        self.ok_button.pressed.connect(self.on_ok)
        button_box.addButton(QDialogButtonBox.Cancel).pressed.connect(
            self.close)

        main_layout = QVBoxLayout()
        main_layout.addWidget(level_group_box)
        main_layout.addWidget(exit_group_box)
        main_layout.addWidget(button_box)

        self.setLayout(main_layout)

        self._set_widget_values()

    def _set_widget_values(self):
        self.screen_spinner.setValue(self.jump.screen_index)

        self.exit_action.setCurrentIndex(self.jump.exit_action)
        self.exit_horizontal.setValue(self.jump.exit_horizontal)
        self.exit_vertical.setCurrentIndex(self.jump.exit_vertical)

    @staticmethod
    def edit_jump(parent: Optional[QWidget], jump: Jump):
        jump_editor = JumpEditor(parent, jump)

        jump_editor.exec_()

        return jump_editor.jump

    def on_ok(self):
        self.jump = Jump.from_properties(
            self.screen_spinner.value(),
            self.exit_action.currentIndex(),
            self.exit_horizontal.value(),
            self.exit_vertical.currentIndex(),
        )

        self.close()
Пример #22
0
class customDesigner(QWidget):
    def __init__(self):
        super().__init__()

        self.fileName = None
        self.filters = "Text files (*.txt)"
        self.customList = QComboBox()
        self.customList.addItems(["Layer", "Loss Function", "Optimizer"])
        self.customList.currentIndexChanged[int].connect(self.editorText)

        self.newButton = QPushButton("New")
        self.newButton.clicked.connect(self.newAction)

        self.saveButton = QPushButton("Save")
        self.saveButton.clicked.connect(self.saveAction)

        self.openButton = QPushButton("Open")
        self.openButton.clicked.connect(self.openAction)
        self.init_GUI()
        self.set_styling()

    def init_GUI(self):
        self.main_layout = QGridLayout()
        self.hbox = QHBoxLayout()
        self.TextEditor = QTextEdit()
        self.TextEditor.setText("class customLayer(Layer):\n\tpass")
        self.hbox.addWidget(self.customList)
        self.hbox.addWidget(self.newButton)
        self.hbox.addWidget(self.saveButton)
        self.hbox.addWidget(self.openButton)
        self.main_layout.addLayout(self.hbox, 0, 0)
        self.main_layout.addWidget(self.TextEditor, 1, 0)
        self.setLayout(self.main_layout)
        self.set_styling()

    def newAction(self):
        response = self.msgApp("Confirmation",
                               "Do you like to save the current file?")
        if response == "Y":
            self.saveAction()
        print(self.customList.currentIndex)
        self.editorText(self.customList.currentIndex())

    def saveAction(self):
        if self.fileName == None or self.fileName == '':
            self.fileName, self.filterName = QFileDialog.getSaveFileName(
                self, filter=self.filters)
        if (self.fileName != ''):
            file = open(self.fileName, 'w')
            file.write(self.TextEditor.toPlainText())

    def openAction(self):
        response = self.msgApp("Confirmation",
                               "Do you like to save the current file?")
        if response == "Y":
            self.saveAction()

        self.fileName, self.filterName = QFileDialog.getOpenFileName(self)
        self.TextEditor.setText(open(self.fileName).read())

    def msgApp(self, title, msg):
        userInfo = QMessageBox.question(self, title, msg,
                                        QMessageBox.Yes | QMessageBox.No)
        if userInfo == QMessageBox.Yes:
            return "Y"
        if userInfo == QMessageBox.No:
            return "N"
        self.close()

    def editorText(self, index):
        if (index == 0):
            self.TextEditor.setText("class customLayer(Layer):\n\tpass")
        if (index == 1):
            self.TextEditor.setText("class customLossFunction():\n\tpass")
        if (index == 2):
            self.TextEditor.setText("class customOptimizer():\n\tpass")

    def set_styling(self):
        pass
Пример #23
0
class PlanesWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(PlanesWidget, self).__init__(parent)

        self.chan_combo = QComboBox()
        self.chan_combo.addItems(
            [self.tr('Luminance'), self.tr('Red'), self.tr('Green'), self.tr('Blue'), self.tr('RGB Norm')])
        self.plane_spin = QSpinBox()
        self.plane_spin.setPrefix(self.tr('Bit '))
        self.plane_spin.setRange(0, 7)
        self.filter_combo = QComboBox()
        self.filter_combo.addItems([self.tr('Disabled'), self.tr('Median'), self.tr('Gaussian')])

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.planes = None
        self.preprocess()

        self.chan_combo.currentIndexChanged.connect(self.preprocess)
        self.plane_spin.valueChanged.connect(self.process)
        self.filter_combo.currentIndexChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Channel:')))
        top_layout.addWidget(self.chan_combo)
        top_layout.addWidget(QLabel(self.tr('Plane:')))
        top_layout.addWidget(self.plane_spin)
        top_layout.addWidget(QLabel(self.tr('Filter:')))
        top_layout.addWidget(self.filter_combo)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def preprocess(self):
        channel = self.chan_combo.currentIndex()
        if channel == 0:
            img = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        elif channel == 4:
            b, g, r = cv.split(self.image.astype(np.float64))
            img = cv.sqrt(cv.pow(b, 2) + cv.pow(g, 2) + cv.pow(r, 2)).astype(np.uint8)
        else:
            img = self.image[:, :, 3 - channel]

        self.planes = [normalize_mat(cv.bitwise_and(np.full_like(img, 2**b), img), to_bgr=True) for b in range(8)]

        # rows, cols = img.shape
        # bits = 8
        # data = [np.binary_repr(img[i][j], width=bits) for i in range(rows) for j in range(cols)]
        # self.planes = [
        #     (np.array([int(i[b]) for i in data], dtype=np.uint8) * 2 ** (bits - b - 1)).reshape(
        #         (rows, cols)) for b in range(bits)]

        self.process()

    def process(self):
        plane = self.planes[self.plane_spin.value()]
        if self.filter_combo.currentIndex() == 1:
            plane = cv.medianBlur(plane, 3)
        elif self.filter_combo.currentIndex() == 2:
            plane = cv.GaussianBlur(plane, (3, 3), 0)
        self.viewer.update_processed(plane)
Пример #24
0
class SettingsDialog(CustomDialog):
    def __init__(self, parent=None):
        super(SettingsDialog, self).__init__(parent, "Settings")

        mouse_box = QGroupBox("Mouse", self)
        mouse_box.setLayout(QVBoxLayout())

        scroll_layout = QHBoxLayout()

        label = QLabel("Scroll objects with mouse wheel:")
        label.setToolTip(
            "Select an object and scroll up and down to change its type.")
        self._scroll_check_box = QCheckBox("Enabled")
        self._scroll_check_box.setChecked(SETTINGS["object_scroll_enabled"])
        self._scroll_check_box.toggled.connect(self._update_settings)

        scroll_layout.addWidget(label)
        scroll_layout.addStretch(1)
        scroll_layout.addWidget(self._scroll_check_box)

        resize_layout = QHBoxLayout()

        self.lmb_radio = QRadioButton("Left Mouse Button")
        rmb_radio = QRadioButton("Right Mouse Button")

        self.lmb_radio.setChecked(SETTINGS["resize_mode"] == RESIZE_LEFT_CLICK)
        rmb_radio.setChecked(SETTINGS["resize_mode"] == RESIZE_RIGHT_CLICK)

        self.lmb_radio.toggled.connect(self._update_settings)

        radio_group = QButtonGroup()
        radio_group.addButton(self.lmb_radio)
        radio_group.addButton(rmb_radio)

        resize_layout.addWidget(QLabel("Object resize mode:"))
        resize_layout.addStretch(1)
        resize_layout.addWidget(self.lmb_radio)
        resize_layout.addWidget(rmb_radio)

        mouse_box.layout().addLayout(scroll_layout)
        mouse_box.layout().addLayout(resize_layout)

        # emulator command

        self.emulator_command_input = QLineEdit(self)
        self.emulator_command_input.setPlaceholderText("Path to emulator")
        self.emulator_command_input.setText(SETTINGS["instaplay_emulator"])

        self.emulator_command_input.textChanged.connect(self._update_settings)

        self.emulator_path_button = QPushButton(icon("folder.svg"), "", self)
        self.emulator_path_button.pressed.connect(self._get_emulator_path)

        self.command_arguments_input = QLineEdit(self)
        self.command_arguments_input.setPlaceholderText("%f")
        self.command_arguments_input.setText(SETTINGS["instaplay_arguments"])

        self.command_arguments_input.textEdited.connect(self._update_settings)

        self.command_label = QLabel()

        command_box = QGroupBox("Emulator", self)
        command_layout = QVBoxLayout(command_box)

        command_layout.addWidget(QLabel('Emulator command or "path to exe":'))

        command_input_layout = QHBoxLayout()
        command_input_layout.addWidget(self.emulator_command_input)
        command_input_layout.addWidget(self.emulator_path_button)

        command_layout.addLayout(command_input_layout)
        command_layout.addWidget(
            QLabel("Command arguments (%f will be replaced with rom path):"))
        command_layout.addWidget(self.command_arguments_input)
        command_layout.addWidget(QLabel("Command used to play the rom:"))
        command_layout.addWidget(self.command_label)

        command_layout.addWidget(HorizontalLine())

        command_layout.addWidget(
            QLabel("Power up of Mario when playing level:"))
        self.powerup_combo_box = QComboBox()

        for name, x, y, value, p_wing in POWERUPS:
            powerup_icon = self._load_from_png(x, y)

            self.powerup_combo_box.addItem(powerup_icon, name)

        self.powerup_combo_box.currentIndexChanged.connect(
            self._update_settings)

        self.powerup_combo_box.setCurrentIndex(SETTINGS["default_powerup"])

        command_layout.addWidget(self.powerup_combo_box)

        # ----------------------

        layout = QVBoxLayout(self)
        layout.addWidget(mouse_box)
        layout.addWidget(command_box)

        self.update()

    def update(self):
        self.command_label.setText(
            f" > {SETTINGS['instaplay_emulator']} {SETTINGS['instaplay_arguments']}"
        )

    def _update_settings(self, _):
        SETTINGS["instaplay_emulator"] = self.emulator_command_input.text()
        SETTINGS["instaplay_arguments"] = self.command_arguments_input.text()

        if self.lmb_radio.isChecked():
            SETTINGS["resize_mode"] = RESIZE_LEFT_CLICK
        else:
            SETTINGS["resize_mode"] = RESIZE_RIGHT_CLICK

        SETTINGS["object_scroll_enabled"] = self._scroll_check_box.isChecked()

        SETTINGS["default_powerup"] = self.powerup_combo_box.currentIndex()

        self.update()

    def _get_emulator_path(self):
        path_to_emulator, _ = QFileDialog.getOpenFileName(
            self, caption="Select emulator executable")

        if not path_to_emulator:
            return

        self.emulator_command_input.setText(path_to_emulator)

    @staticmethod
    def _load_from_png(x: int, y: int) -> QIcon:
        image = png.copy(QRect(x * 16, y * 16, 16, 16))
        mask = image.createMaskFromColor(
            QColor(*MASK_COLOR).rgb(), Qt.MaskOutColor)
        image.setAlphaChannel(mask)

        pixmap = QPixmap.fromImage(image)
        icon = QIcon(pixmap)

        return icon

    def on_exit(self):
        save_settings()

        super(SettingsDialog, self).on_exit()
Пример #25
0
class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.iconGroupBox = QGroupBox()
        self.iconLabel = QLabel()
        self.iconComboBox = QComboBox()
        self.showIconCheckBox = QCheckBox()

        self.messageGroupBox = QGroupBox()
        self.typeLabel = QLabel()
        self.durationLabel = QLabel()
        self.durationWarningLabel = QLabel()
        self.titleLabel = QLabel()
        self.bodyLabel = QLabel()

        self.typeComboBox = QComboBox()
        self.durationSpinBox = QSpinBox()
        self.titleEdit = QLineEdit()
        self.bodyEdit = QTextEdit()
        self.showMessageButton = QPushButton()

        self.minimizeAction = QAction()
        self.maximizeAction = QAction()
        self.restoreAction = QAction()
        self.quitAction = QAction()

        self.trayIcon = QSystemTrayIcon()
        self.trayIconMenu = QMenu()

        self.createIconGroupBox()
        self.createMessageGroupBox()

        self.iconLabel.setMinimumWidth(self.durationLabel.sizeHint().width())

        self.createActions()
        self.createTrayIcon()

        self.showMessageButton.clicked.connect(self.showMessage)
        self.showIconCheckBox.toggled.connect(self.trayIcon.setVisible)
        self.iconComboBox.currentIndexChanged.connect(self.setIcon)
        self.trayIcon.messageClicked.connect(self.messageClicked)
        self.trayIcon.activated.connect(self.iconActivated)

        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.iconGroupBox)
        self.mainLayout.addWidget(self.messageGroupBox)
        self.setLayout(self.mainLayout)

        self.iconComboBox.setCurrentIndex(1)
        self.trayIcon.show()

        self.setWindowTitle("Systray")
        self.resize(400, 300)

    def setVisible(self, visible):
        self.minimizeAction.setEnabled(visible)
        self.maximizeAction.setEnabled(not self.isMaximized())
        self.restoreAction.setEnabled(self.isMaximized() or not visible)
        super().setVisible(visible)

    def closeEvent(self, event):
        if not event.spontaneous() or not self.isVisible():
            return
        if self.trayIcon.isVisible():
            QMessageBox.information(self, "Systray",
                                    "The program will keep running in the system tray. "
                                    "To terminate the program, choose <b>Quit</b> in the context "
                                    "menu of the system tray entry.")
            self.hide()
            event.ignore()

    @Slot(int)
    def setIcon(self, index):
        icon = self.iconComboBox.itemIcon(index)
        self.trayIcon.setIcon(icon)
        self.setWindowIcon(icon)
        self.trayIcon.setToolTip(self.iconComboBox.itemText(index))

    @Slot(str)
    def iconActivated(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            pass
        if reason == QSystemTrayIcon.DoubleClick:
            self.iconComboBox.setCurrentIndex(
                (self.iconComboBox.currentIndex() + 1) % self.iconComboBox.count()
            )
        if reason == QSystemTrayIcon.MiddleClick:
            self.showMessage()

    @Slot()
    def showMessage(self):
        self.showIconCheckBox.setChecked(True)
        selectedIcon = self.typeComboBox.itemData(self.typeComboBox.currentIndex())
        msgIcon = QSystemTrayIcon.MessageIcon(selectedIcon)

        if selectedIcon == -1:  # custom icon
            icon = QIcon(self.iconComboBox.itemIcon(self.iconComboBox.currentIndex()))
            self.trayIcon.showMessage(
                self.titleEdit.text(),
                self.bodyEdit.toPlainText(),
                icon,
                self.durationSpinBox.value() * 1000,
            )
        else:
            self.trayIcon.showMessage(
                self.titleEdit.text(),
                self.bodyEdit.toPlainText(),
                msgIcon,
                self.durationSpinBox.value() * 1000,
            )

    @Slot()
    def messageClicked(self):
        QMessageBox.information(None, "Systray",
                                "Sorry, I already gave what help I could.\n"
                                "Maybe you should try asking a human?")

    def createIconGroupBox(self):
        self.iconGroupBox = QGroupBox("Tray Icon")

        self.iconLabel = QLabel("Icon:")

        self.iconComboBox = QComboBox()
        self.iconComboBox.addItem(QIcon(":/images/bad.png"), "Bad")
        self.iconComboBox.addItem(QIcon(":/images/heart.png"), "Heart")
        self.iconComboBox.addItem(QIcon(":/images/trash.png"), "Trash")

        self.showIconCheckBox = QCheckBox("Show icon")
        self.showIconCheckBox.setChecked(True)

        iconLayout = QHBoxLayout()
        iconLayout.addWidget(self.iconLabel)
        iconLayout.addWidget(self.iconComboBox)
        iconLayout.addStretch()
        iconLayout.addWidget(self.showIconCheckBox)
        self.iconGroupBox.setLayout(iconLayout)

    def createMessageGroupBox(self):
        self.messageGroupBox = QGroupBox("Balloon Message")

        self.typeLabel = QLabel("Type:")

        self.typeComboBox = QComboBox()
        self.typeComboBox.addItem("None", QSystemTrayIcon.NoIcon)
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxInformation),
            "Information",
            QSystemTrayIcon.Information,
        )
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxWarning),
            "Warning",
            QSystemTrayIcon.Warning,
        )
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxCritical),
            "Critical",
            QSystemTrayIcon.Critical,
        )
        self.typeComboBox.addItem(QIcon(), "Custom icon", -1)
        self.typeComboBox.setCurrentIndex(1)

        self.durationLabel = QLabel("Duration:")

        self.durationSpinBox = QSpinBox()
        self.durationSpinBox.setRange(5, 60)
        self.durationSpinBox.setSuffix(" s")
        self.durationSpinBox.setValue(15)

        self.durationWarningLabel = QLabel("(some systems might ignore this hint)")
        self.durationWarningLabel.setIndent(10)

        self.titleLabel = QLabel("Title:")
        self.titleEdit = QLineEdit("Cannot connect to network")
        self.bodyLabel = QLabel("Body:")

        self.bodyEdit = QTextEdit()
        self.bodyEdit.setPlainText("Don't believe me. Honestly, I don't have a clue."
                                   "\nClick this balloon for details.")

        self.showMessageButton = QPushButton("Show Message")
        self.showMessageButton.setDefault(True)

        messageLayout = QGridLayout()
        messageLayout.addWidget(self.typeLabel, 0, 0)
        messageLayout.addWidget(self.typeComboBox, 0, 1, 1, 2)
        messageLayout.addWidget(self.durationLabel, 1, 0)
        messageLayout.addWidget(self.durationSpinBox, 1, 1)
        messageLayout.addWidget(self.durationWarningLabel, 1, 2, 1, 3)
        messageLayout.addWidget(self.titleLabel, 2, 0)
        messageLayout.addWidget(self.titleEdit, 2, 1, 1, 4)
        messageLayout.addWidget(self.bodyLabel, 3, 0)
        messageLayout.addWidget(self.bodyEdit, 3, 1, 2, 4)
        messageLayout.addWidget(self.showMessageButton, 5, 4)
        messageLayout.setColumnStretch(3, 1)
        messageLayout.setRowStretch(4, 1)
        self.messageGroupBox.setLayout(messageLayout)

    def createActions(self):
        self.minimizeAction = QAction("Minimize", self)
        self.minimizeAction.triggered.connect(self.hide)

        self.maximizeAction = QAction("Maximize", self)
        self.maximizeAction.triggered.connect(self.showMaximized)

        self.restoreAction = QAction("Restore", self)
        self.restoreAction.triggered.connect(self.showNormal)

        self.quitAction = QAction("Quit", self)
        self.quitAction.triggered.connect(qApp.quit)

    def createTrayIcon(self):
        self.trayIconMenu = QMenu(self)
        self.trayIconMenu.addAction(self.minimizeAction)
        self.trayIconMenu.addAction(self.maximizeAction)
        self.trayIconMenu.addAction(self.restoreAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)

        self.trayIcon = QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
Пример #26
0
class HeaderEditor(CustomDialog):
    header_change: SignalInstance = Signal()

    def __init__(self, parent: Optional[QWindow], level_ref: LevelRef):
        super(HeaderEditor, self).__init__(parent, "Level Header Editor")

        self.level: Level = level_ref.level

        # enables undo
        self.header_change.connect(level_ref.save_level_state)

        main_layout = QVBoxLayout(self)

        tab_widget = QTabWidget(self)
        main_layout.addWidget(tab_widget)

        # level settings

        self.length_dropdown = QComboBox()
        self.length_dropdown.addItems(STR_LEVEL_LENGTHS)
        self.length_dropdown.activated.connect(self.on_combo)

        self.music_dropdown = QComboBox()
        self.music_dropdown.addItems(MUSIC_ITEMS)
        self.music_dropdown.activated.connect(self.on_combo)

        self.time_dropdown = QComboBox()
        self.time_dropdown.addItems(TIMES)
        self.time_dropdown.activated.connect(self.on_combo)

        self.v_scroll_direction_dropdown = QComboBox()
        self.v_scroll_direction_dropdown.addItems(SCROLL_DIRECTIONS)
        self.v_scroll_direction_dropdown.activated.connect(self.on_combo)

        self.level_is_vertical_cb = QCheckBox("Level is Vertical")
        self.level_is_vertical_cb.clicked.connect(self.on_check_box)

        self.pipe_ends_level_cb = QCheckBox("Pipe ends Level")
        self.pipe_ends_level_cb.clicked.connect(self.on_check_box)

        check_box_layout = QHBoxLayout()
        check_box_layout.setContentsMargins(0, 0, 0, 0)
        check_box_layout.addWidget(self.level_is_vertical_cb)
        check_box_layout.addWidget(self.pipe_ends_level_cb)

        check_box_widget = QWidget()
        check_box_widget.setLayout(check_box_layout)

        form = QFormLayout()
        form.setFormAlignment(Qt.AlignCenter)

        form.addRow("Level length: ", self.length_dropdown)
        form.addRow("Music: ", self.music_dropdown)
        form.addRow("Time: ", self.time_dropdown)
        form.addRow("Scroll direction: ", self.v_scroll_direction_dropdown)

        form.addWidget(check_box_widget)

        widget = QWidget()
        widget.setLayout(form)

        tab_widget.addTab(widget, "Level")

        # player settings

        self.x_position_dropdown = QComboBox()
        self.x_position_dropdown.addItems(STR_X_POSITIONS)
        self.x_position_dropdown.activated.connect(self.on_combo)

        self.y_position_dropdown = QComboBox()
        self.y_position_dropdown.addItems(STR_Y_POSITIONS)
        self.y_position_dropdown.activated.connect(self.on_combo)

        self.action_dropdown = QComboBox()
        self.action_dropdown.addItems(ACTIONS)
        self.action_dropdown.activated.connect(self.on_combo)

        form = QFormLayout()
        form.setFormAlignment(Qt.AlignCenter)

        form.addRow("Starting X: ", self.x_position_dropdown)
        form.addRow("Starting Y: ", self.y_position_dropdown)
        form.addRow("Action: ", self.action_dropdown)

        widget = QWidget()
        widget.setLayout(form)

        tab_widget.addTab(widget, "Mario")

        # graphic settings

        self.object_palette_spinner = Spinner(self, maximum=7)
        self.object_palette_spinner.valueChanged.connect(self.on_spin)

        self.enemy_palette_spinner = Spinner(self, maximum=3)
        self.enemy_palette_spinner.valueChanged.connect(self.on_spin)

        self.graphic_set_dropdown = QComboBox()
        self.graphic_set_dropdown.addItems(GRAPHIC_SETS)
        self.graphic_set_dropdown.activated.connect(self.on_combo)

        form = QFormLayout()
        form.setFormAlignment(Qt.AlignCenter)

        form.addRow("Object Palette: ", self.object_palette_spinner)
        form.addRow("Enemy Palette: ", self.enemy_palette_spinner)
        form.addRow("Graphic Set: ", self.graphic_set_dropdown)

        widget = QWidget()
        widget.setLayout(form)

        tab_widget.addTab(widget, "Graphics")

        # next area settings

        self.level_pointer_spinner = Spinner(self, maximum=SPINNER_MAX_VALUE)
        self.level_pointer_spinner.valueChanged.connect(self.on_spin)
        self.enemy_pointer_spinner = Spinner(self, maximum=SPINNER_MAX_VALUE)
        self.enemy_pointer_spinner.valueChanged.connect(self.on_spin)

        self.next_area_object_set_dropdown = QComboBox()
        self.next_area_object_set_dropdown.addItems(OBJECT_SET_ITEMS)
        self.next_area_object_set_dropdown.activated.connect(self.on_combo)

        level_select_button = QPushButton("Set from Level")
        level_select_button.pressed.connect(self._set_jump_destination)

        form = QFormLayout()
        form.setFormAlignment(Qt.AlignCenter)

        form.addRow("Address of Objects: ", self.level_pointer_spinner)
        form.addRow("Address of Enemies: ", self.enemy_pointer_spinner)
        form.addRow("Object Set: ", self.next_area_object_set_dropdown)

        form.addRow(QLabel(""))
        form.addRow(level_select_button)

        widget = QWidget()
        widget.setLayout(form)

        tab_widget.addTab(widget, "Jump Destination")

        self.header_bytes_label = QLabel()

        main_layout.addWidget(self.header_bytes_label,
                              alignment=Qt.AlignCenter)

        self.update()

    def update(self):
        length_index = LEVEL_LENGTHS.index(self.level.length)

        self.length_dropdown.setCurrentIndex(length_index)
        self.music_dropdown.setCurrentIndex(self.level.music_index)
        self.time_dropdown.setCurrentIndex(self.level.time_index)
        self.v_scroll_direction_dropdown.setCurrentIndex(
            self.level.scroll_type)
        self.level_is_vertical_cb.setChecked(self.level.is_vertical)
        self.pipe_ends_level_cb.setChecked(self.level.pipe_ends_level)

        self.x_position_dropdown.setCurrentIndex(self.level.start_x_index)
        self.y_position_dropdown.setCurrentIndex(self.level.start_y_index)
        self.action_dropdown.setCurrentIndex(self.level.start_action)

        self.object_palette_spinner.setValue(self.level.object_palette_index)
        self.enemy_palette_spinner.setValue(self.level.enemy_palette_index)
        self.graphic_set_dropdown.setCurrentIndex(self.level.graphic_set)

        self.level_pointer_spinner.setValue(self.level.next_area_objects)
        self.enemy_pointer_spinner.setValue(self.level.next_area_enemies)
        self.next_area_object_set_dropdown.setCurrentIndex(
            self.level.next_area_object_set)

        self.header_bytes_label.setText(" ".join(
            f"{number:0=#4X}"[2:] for number in self.level.header_bytes))

    def _set_jump_destination(self):
        level_selector = LevelSelector(self)
        level_was_selected = level_selector.exec_() == QDialog.Accepted

        if not level_was_selected:
            return

        self.next_area_object_set_dropdown.setCurrentIndex(
            level_selector.object_set)
        self.level.next_area_object_set = level_selector.object_set

        self.level_pointer_spinner.setValue(level_selector.object_data_offset)
        self.level.next_area_objects = level_selector.object_data_offset

        self.enemy_pointer_spinner.setValue(level_selector.enemy_data_offset)
        self.level.next_area_enemies = level_selector.enemy_data_offset - 1

        self.header_change.emit()

    def on_spin(self, _):
        if self.level is None:
            return

        spinner = self.sender()

        self.level.data_changed.connect(self.header_change.emit)

        if spinner == self.object_palette_spinner:
            new_index = self.object_palette_spinner.value()
            self.level.object_palette_index = new_index

        elif spinner == self.enemy_palette_spinner:
            new_index = self.enemy_palette_spinner.value()
            self.level.enemy_palette_index = new_index

        elif spinner == self.level_pointer_spinner:
            new_offset = self.level_pointer_spinner.value()
            self.level.next_area_objects = new_offset

        elif spinner == self.enemy_pointer_spinner:
            new_offset = self.enemy_pointer_spinner.value()
            self.level.next_area_enemies = new_offset

        self.level.data_changed.disconnect(self.header_change.emit)

        self.update()

    def on_combo(self, _):
        dropdown = self.sender()

        self.level.data_changed.connect(self.header_change.emit)

        if dropdown == self.length_dropdown:
            new_length = LEVEL_LENGTHS[self.length_dropdown.currentIndex()]
            self.level.length = new_length

        elif dropdown == self.music_dropdown:
            new_music = self.music_dropdown.currentIndex()
            self.level.music_index = new_music

        elif dropdown == self.time_dropdown:
            new_time = self.time_dropdown.currentIndex()
            self.level.time_index = new_time

        elif dropdown == self.v_scroll_direction_dropdown:
            new_scroll = self.v_scroll_direction_dropdown.currentIndex()
            self.level.scroll_type = new_scroll

        elif dropdown == self.x_position_dropdown:
            new_x = self.x_position_dropdown.currentIndex()
            self.level.start_x_index = new_x

        elif dropdown == self.y_position_dropdown:
            new_y = self.y_position_dropdown.currentIndex()
            self.level.start_y_index = new_y

        elif dropdown == self.action_dropdown:
            new_action = self.action_dropdown.currentIndex()
            self.level.start_action = new_action

        elif dropdown == self.graphic_set_dropdown:
            new_gfx_set = self.graphic_set_dropdown.currentIndex()
            self.level.graphic_set = new_gfx_set

        elif dropdown == self.next_area_object_set_dropdown:
            new_object_set = self.next_area_object_set_dropdown.currentIndex()
            self.level.next_area_object_set = new_object_set

        self.level.data_changed.disconnect(self.header_change.emit)

        self.update()

    def on_check_box(self, _):
        checkbox = self.sender()

        self.level.data_changed.connect(self.header_change.emit)

        if checkbox == self.pipe_ends_level_cb:
            self.level.pipe_ends_level = self.pipe_ends_level_cb.isChecked()
        elif checkbox == self.level_is_vertical_cb:
            self.level.is_vertical = self.level_is_vertical_cb.isChecked()

        self.level.data_changed.disconnect(self.header_change.emit)

        self.update()
Пример #27
0
class EMMAResolverPanel(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent=parent, f=Qt.Window)
        self.setWindowTitle(self.tr("EMMA Resolver"))
        self.SUPPORTED_DISTS = \
            [(DistributionType.Nonparametric, self.tr("Nonparametric")),
             (DistributionType.Normal, self.tr("Normal")),
             (DistributionType.Weibull, self.tr("Weibull")),
             (DistributionType.SkewNormal, self.tr("Skew Normal"))]

        self.init_ui()
        self.normal_msg = QMessageBox(self)
        self.__dataset = None  # type: GrainSizeDataset
        self.__result_list = []  # type: list[EMMAResult]
        self.neural_setting = NNResolverSettingWidget(parent=self)
        self.neural_setting.setting = NNResolverSetting(min_niter=800,
                                                        max_niter=1200,
                                                        tol=1e-6,
                                                        ftol=1e-8,
                                                        lr=5e-2)
        self.load_dialog = LoadDatasetDialog(parent=self)
        self.load_dialog.dataset_loaded.connect(self.on_dataset_loaded)
        self.file_dialog = QFileDialog(parent=self)
        self.emma_result_chart = EMMAResultChart(toolbar=True)
        self.emma_summary_chart = EMMASummaryChart(toolbar=True)

    def init_ui(self):
        self.setAttribute(Qt.WA_StyledBackground, True)
        self.main_layout = QGridLayout(self)
        # self.main_layout.setContentsMargins(0, 0, 0, 0)
        # control group
        self.control_group = QGroupBox(self.tr("Control"))
        self.control_layout = QGridLayout(self.control_group)
        self.main_layout.addWidget(self.control_group, 0, 0)
        self.load_dataset_button = QPushButton(qta.icon("fa.database"),
                                               self.tr("Load Dataset"))
        self.load_dataset_button.clicked.connect(self.on_load_clicked)
        self.control_layout.addWidget(self.load_dataset_button, 0, 0, 1, 2)
        self.configure_button = QPushButton(qta.icon("fa.gears"),
                                            self.tr("Configure Algorithm"))
        self.configure_button.clicked.connect(self.on_configure_clicked)
        self.control_layout.addWidget(self.configure_button, 1, 0, 1, 2)
        self.n_samples_label = QLabel(self.tr("N<sub>samples</sub>"))
        self.n_samples_display = QLabel(self.tr("Unknown"))
        self.control_layout.addWidget(self.n_samples_label, 2, 0)
        self.control_layout.addWidget(self.n_samples_display, 2, 1)
        self.distribution_label = QLabel(self.tr("Distribution Type"))
        self.distribution_combo_box = QComboBox()
        self.distribution_combo_box.addItems(
            [name for _, name in self.SUPPORTED_DISTS])
        self.control_layout.addWidget(self.distribution_label, 3, 0)
        self.control_layout.addWidget(self.distribution_combo_box, 3, 1)
        self.min_n_members_label = QLabel("Minimum N<sub>members</sub>")
        self.min_n_members_input = QSpinBox()
        self.min_n_members_input.setRange(1, 10)
        self.control_layout.addWidget(self.min_n_members_label, 4, 0)
        self.control_layout.addWidget(self.min_n_members_input, 4, 1)
        self.max_n_members_label = QLabel("Maximum N<sub>members</sub>")
        self.max_n_members_input = QSpinBox()
        self.max_n_members_input.setRange(1, 10)
        self.max_n_members_input.setValue(10)
        self.control_layout.addWidget(self.max_n_members_label, 5, 0)
        self.control_layout.addWidget(self.max_n_members_input, 5, 1)
        self.perform_button = QPushButton(qta.icon("fa.play-circle"),
                                          self.tr("Perform"))
        self.perform_button.clicked.connect(self.on_perform_clicked)
        self.perform_button.setEnabled(False)
        self.perform_with_customized_ems_button = QPushButton(
            qta.icon("fa.play-circle"), self.tr("Perform With Customized EMs"))
        self.perform_with_customized_ems_button.clicked.connect(
            self.on_perform_with_customized_ems)
        self.perform_with_customized_ems_button.setEnabled(False)
        self.control_layout.addWidget(self.perform_button, 6, 0, 1, 2)
        self.control_layout.addWidget(self.perform_with_customized_ems_button,
                                      7, 0, 1, 2)
        self.progress_bar = QProgressBar()
        self.progress_bar.setFormat(self.tr("EMMA Progress"))
        self.control_layout.addWidget(self.progress_bar, 8, 0, 1, 2)

        self.result_group = QGroupBox(self.tr("Result"))
        self.result_layout = QGridLayout(self.result_group)
        self.main_layout.addWidget(self.result_group, 0, 1)
        self.result_list_widget = QListWidget()
        self.result_layout.addWidget(self.result_list_widget, 0, 0, 1, 2)
        self.remove_result_button = QPushButton(qta.icon("mdi.delete"),
                                                self.tr("Remove"))
        self.remove_result_button.clicked.connect(self.on_remove_clicked)
        self.show_result_button = QPushButton(qta.icon("fa.area-chart"),
                                              self.tr("Show"))
        self.show_result_button.clicked.connect(self.on_show_clicked)
        self.load_dump_button = QPushButton(qta.icon("fa.database"),
                                            self.tr("Load Dump"))
        self.load_dump_button.clicked.connect(self.on_load_dump_clicked)
        self.save_button = QPushButton(qta.icon("fa.save"), self.tr("Save"))
        self.save_button.clicked.connect(self.on_save_clicked)
        self.remove_result_button.setEnabled(False)
        self.show_result_button.setEnabled(False)
        self.save_button.setEnabled(False)
        self.result_layout.addWidget(self.remove_result_button, 1, 0)
        self.result_layout.addWidget(self.show_result_button, 1, 1)
        self.result_layout.addWidget(self.load_dump_button, 2, 0)
        self.result_layout.addWidget(self.save_button, 2, 1)

    def show_message(self, title: str, message: str):
        self.normal_msg.setWindowTitle(title)
        self.normal_msg.setText(message)
        self.normal_msg.exec_()

    def show_info(self, message: str):
        self.show_message(self.tr("Info"), message)

    def show_warning(self, message: str):
        self.show_message(self.tr("Warning"), message)

    def show_error(self, message: str):
        self.show_message(self.tr("Error"), message)

    def on_dataset_loaded(self, dataset: GrainSizeDataset):
        self.__dataset = dataset
        self.n_samples_display.setText(str(self.__dataset.n_samples))
        self.perform_button.setEnabled(True)
        self.perform_with_customized_ems_button.setEnabled(True)

    def on_load_clicked(self):
        self.load_dialog.show()

    def on_configure_clicked(self):
        self.neural_setting.show()

    @property
    def distribution_type(self) -> DistributionType:
        distribution_type, _ = self.SUPPORTED_DISTS[
            self.distribution_combo_box.currentIndex()]
        return distribution_type

    @property
    def n_members_list(self):
        min_n = self.min_n_members_input.value()
        max_n = self.max_n_members_input.value()
        if min_n > max_n:
            min_n, max_n = max_n, min_n
        return list(range(min_n, max_n + 1, 1))

    @property
    def n_results(self) -> int:
        return len(self.__result_list)

    @property
    def selected_index(self):
        indexes = self.result_list_widget.selectedIndexes()
        if len(indexes) == 0:
            return 0
        else:
            return indexes[0].row()

    @property
    def selected_result(self):
        if self.n_results == 0:
            None
        else:
            return self.__result_list[self.selected_index]

    def on_perform_clicked(self):
        if self.__dataset is None:
            self.show_error(self.tr("Dataset has not been loaded."))
            return

        self.perform_button.setEnabled(False)
        self.perform_with_customized_ems_button.setEnabled(False)
        resolver = EMMAResolver()
        resolver_setting = self.neural_setting.setting
        results = []
        n_members_list = self.n_members_list
        self.progress_bar.setRange(0, len(n_members_list))
        self.progress_bar.setValue(0)
        self.progress_bar.setFormat(self.tr("Performing EMMA [%v/%m]"))
        QCoreApplication.processEvents()
        for i, n_members in enumerate(n_members_list):
            result = resolver.try_fit(self.__dataset, self.distribution_type,
                                      n_members, resolver_setting)
            results.append(result)
            self.progress_bar.setValue(i + 1)
            QCoreApplication.processEvents()

        self.add_results(results)
        self.progress_bar.setFormat(self.tr("Finished"))
        self.perform_button.setEnabled(True)
        self.perform_with_customized_ems_button.setEnabled(True)
        if len(results) > 1:
            self.emma_summary_chart.show_distances(results)
            self.emma_summary_chart.show()

    def on_perform_with_customized_ems(self):
        if self.__dataset is None:
            self.show_error(self.tr("Dataset has not been loaded."))
            return

        filename, _ = self.file_dialog.getOpenFileName(
            self,
            self.
            tr("Choose a excel file which contains the customized EMs at the first sheet"
               ), None, f"{self.tr('Microsoft Excel')} (*.xlsx)")
        if filename is None or filename == "":
            return
        try:
            wb = openpyxl.load_workbook(filename,
                                        read_only=True,
                                        data_only=True)
            ws = wb[wb.sheetnames[0]]
            raw_data = [[value for value in row] for row in ws.values]
            classes_μm = np.array(raw_data[0][1:], dtype=np.float64)
            classes_φ = convert_μm_to_φ(classes_μm)
            em_distributions = [
                np.array(row[1:], dtype=np.float64) for row in raw_data[1:]
            ]
        except Exception as e:
            self.show_error(
                self.tr(
                    "Error raised while loading the customized EMs.\n    {0}").
                format(e.__str__()))
            return
        if len(classes_μm) < 10:
            self.show_error(
                self.tr("The length of grain-size classes is too less."))
            return
        for i in range(len(classes_μm) - 1):
            if classes_μm[i + 1] <= classes_μm[i]:
                self.show_error(
                    self.tr("The grain-size classes is not incremental."))
                return
        if np.any(np.isnan(classes_μm)):
            self.show_error(
                self.tr(
                    "There is at least one nan value in grain-size classes."))
            return
        if len(em_distributions) > 10:
            self.show_error(
                self.
                tr("There are more than 10 customized EMs in the first sheet, please check."
                   ))
            return
        for distribution in em_distributions:
            if len(classes_μm) != len(distribution):
                self.show_error(
                    self.
                    tr("Some distributions of customized EMs have different length with the grain-size classes."
                       ))
                return
            if np.any(np.isnan(distribution)):
                self.show_error(
                    self.
                    tr("There is at least one nan value in the frequceny distributions of EMs."
                       ))
                return
            if abs(np.sum(distribution) - 1.0) > 0.05:
                self.show_error(
                    self.
                    tr("The sum of some distributions of customized EMs are not equal to 1."
                       ))
                return

        self.perform_button.setEnabled(False)
        self.perform_with_customized_ems_button.setEnabled(False)
        resolver = EMMAResolver()
        resolver_setting = self.neural_setting.setting

        self.progress_bar.setRange(0, 1)
        self.progress_bar.setValue(0)
        self.progress_bar.setFormat(self.tr("Performing EMMA [%v/%m]"))
        QCoreApplication.processEvents()
        try:
            result = resolver.try_fit_with_fixed_ems(self.__dataset, classes_φ,
                                                     em_distributions,
                                                     resolver_setting)
            self.progress_bar.setValue(1)
            self.add_results([result])
            self.progress_bar.setFormat(self.tr("Finished"))
        except Exception as e:
            self.show_error(
                self.tr("Error raised while fitting.\n    {0}").format(
                    e.__str__()))
            self.progress_bar.setFormat(self.tr("Failed"))
        QCoreApplication.processEvents()
        self.perform_button.setEnabled(True)
        self.perform_with_customized_ems_button.setEnabled(True)

    def get_distribution_name(self, distribution_type: DistributionType):
        if distribution_type == DistributionType.Nonparametric:
            return self.tr("Nonparametric")
        elif distribution_type == DistributionType.Normal:
            return self.tr("Normal")
        elif distribution_type == DistributionType.Weibull:
            return self.tr("Weibull")
        elif distribution_type == DistributionType.SkewNormal:
            return self.tr("Skew Normal")
        elif distribution_type == DistributionType.Customized:
            return self.tr("Customized")
        else:
            raise NotImplementedError(distribution_type)

    def get_result_name(self, result: EMMAResult):
        return f"[{self.get_distribution_name(result.distribution_type)}]-[{result.n_members} EM(s)]"

    def add_results(self, results: typing.List[EMMAResult]):
        if self.n_results == 0:
            self.remove_result_button.setEnabled(True)
            self.show_result_button.setEnabled(True)
            self.save_button.setEnabled(True)

        self.__result_list.extend(results)
        self.result_list_widget.addItems(
            [self.get_result_name(result) for result in results])

    def on_remove_clicked(self):
        if self.n_results == 0:
            return
        else:
            index = self.selected_index
            self.__result_list.pop(index)
            self.result_list_widget.takeItem(index)

        if self.n_results == 0:
            self.remove_result_button.setEnabled(False)
            self.show_result_button.setEnabled(False)
            self.save_button.setEnabled(False)

    def on_show_clicked(self):
        result = self.selected_result
        if result is None:
            return
        else:
            self.emma_result_chart.show_result(result)
            self.emma_result_chart.show()

    def on_load_dump_clicked(self):
        filename, _ = self.file_dialog.getOpenFileName(
            self, self.tr("Select the dump file of the EMMA result(s)"), None,
            f"{self.tr('Binary Dump')} (*.dump)")
        if filename is None or filename == "":
            return
        with open(filename, "rb") as f:
            results = pickle.load(f)
            invalid = False
            if isinstance(results, list):
                for result in results:
                    if not isinstance(result, EMMAResult):
                        invalid = True
                        break
            else:
                invalid = True
            if invalid:
                self.show_error(
                    self.tr("The dump file does not contain any EMMA result."))
                return
            else:
                self.add_results(results)

    def save_result_excel(self, filename: str, result: EMMAResult):
        # get the mode size of each end-members
        modes = [(i, result.dataset.classes_μm[np.unravel_index(
            np.argmax(result.end_members[i]), result.end_members[i].shape)])
                 for i in range(result.n_members)]
        # sort them by mode size
        modes.sort(key=lambda x: x[1])
        wb = openpyxl.Workbook()
        prepare_styles(wb)

        ws = wb.active
        ws.title = self.tr("README")
        description = \
            """
            This Excel file was generated by QGrain ({0}).

            Please cite:
            Liu, Y., Liu, X., Sun, Y., 2021. QGrain: An open-source and easy-to-use software for the comprehensive analysis of grain size distributions. Sedimentary Geology 423, 105980. https://doi.org/10.1016/j.sedgeo.2021.105980

            It contanins three sheets:
            1. The first sheet is the dataset which was used to perform the EMMA algorithm.
            2. The second sheet is used to put the distributions of all end-members.
            3. The third sheet is the end-member fractions of all samples.

            This EMMA algorithm was implemented by QGrian, using the famous machine learning framework, PyTorch.

            EMMA algorithm details
                N_samples: {1},
                Distribution Type: {2},
                N_members: {3},
                N_iterations: {4},
                Spent Time: {5} s,

                Computing Device: {6},
                Distance: {7},
                Minimum N_iterations: {8},
                Maximum N_iterations: {9},
                Learning Rate: {10},
                eps: {11},
                tol: {12},
                ftol: {13}

            """.format(QGRAIN_VERSION,
                    result.dataset.n_samples,
                    result.distribution_type.name,
                    result.n_members,
                    result.n_iterations,
                    result.time_spent,
                    result.resolver_setting.device,
                    result.resolver_setting.distance,
                    result.resolver_setting.min_niter,
                    result.resolver_setting.max_niter,
                    result.resolver_setting.lr,
                    result.resolver_setting.eps,
                    result.resolver_setting.tol,
                    result.resolver_setting.ftol)

        def write(row, col, value, style="normal_light"):
            cell = ws.cell(row + 1, col + 1, value=value)
            cell.style = style

        lines_of_desc = description.split("\n")
        for row, line in enumerate(lines_of_desc):
            write(row, 0, line, style="description")
        ws.column_dimensions[column_to_char(0)].width = 200

        ws = wb.create_sheet(self.tr("Dataset"))
        write(0, 0, self.tr("Sample Name"), style="header")
        ws.column_dimensions[column_to_char(0)].width = 16
        for col, value in enumerate(result.dataset.classes_μm, 1):
            write(0, col, value, style="header")
            ws.column_dimensions[column_to_char(col)].width = 10
        for row, sample in enumerate(result.dataset.samples, 1):
            if row % 2 == 0:
                style = "normal_dark"
            else:
                style = "normal_light"
            write(row, 0, sample.name, style=style)
            for col, value in enumerate(sample.distribution, 1):
                write(row, col, value, style=style)
            QCoreApplication.processEvents()

        ws = wb.create_sheet(self.tr("End-members"))
        write(0, 0, self.tr("End-member"), style="header")
        ws.column_dimensions[column_to_char(0)].width = 16
        for col, value in enumerate(result.dataset.classes_μm, 1):
            write(0, col, value, style="header")
            ws.column_dimensions[column_to_char(col)].width = 10
        for row, (index, _) in enumerate(modes, 1):
            if row % 2 == 0:
                style = "normal_dark"
            else:
                style = "normal_light"
            write(row, 0, f"EM{row}", style=style)
            for col, value in enumerate(result.end_members[index], 1):
                write(row, col, value, style=style)
            QCoreApplication.processEvents()

        ws = wb.create_sheet(self.tr("Fractions"))
        write(0, 0, self.tr("Sample Name"), style="header")
        ws.column_dimensions[column_to_char(0)].width = 16
        for i in range(result.n_members):
            write(0, i + 1, f"EM{i+1}", style="header")
            ws.column_dimensions[column_to_char(i + 1)].width = 10
        for row, fractions in enumerate(result.fractions, 1):
            if row % 2 == 0:
                style = "normal_dark"
            else:
                style = "normal_light"
            write(row, 0, result.dataset.samples[row - 1].name, style=style)
            for col, (index, _) in enumerate(modes, 1):
                write(row, col, fractions[index], style=style)
            QCoreApplication.processEvents()

        wb.save(filename)
        wb.close()

    def on_save_clicked(self):
        if self.n_results == 0:
            self.show_warning(
                self.tr("There is not an EMMA result in the list."))
            return

        filename, _ = self.file_dialog.getSaveFileName(
            self,
            self.tr("Choose a filename to save the EMMA result(s) in list"),
            None,
            f"{self.tr('Binary Dump')} (*.dump);;{self.tr('Microsoft Excel')} (*.xlsx)"
        )
        if filename is None or filename == "":
            return
        _, ext = os.path.splitext(filename)

        if ext == ".dump":
            with open(filename, "wb") as f:
                pickle.dump(self.__result_list, f)
                self.show_info(self.tr("All results in list has been saved."))
        elif ext == ".xlsx":
            try:
                result = self.selected_result
                self.save_result_excel(filename, result)
                self.show_info(self.tr("The selected result has been saved."))
            except Exception as e:
                self.show_error(
                    self.tr(
                        "Error raised while saving it to Excel file.\n    {0}"
                    ).format(e.__str__()))
                return
Пример #28
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.proxyModel = SortFilterProxyModel()
        self.proxyModel.setDynamicSortFilter(True)

        self.sourceGroupBox = QGroupBox("Original Model")
        self.proxyGroupBox = QGroupBox("Sorted/Filtered Model")

        self.sourceView = QTreeView()
        self.sourceView.setRootIsDecorated(False)
        self.sourceView.setAlternatingRowColors(True)

        self.proxyView = QTreeView()
        self.proxyView.setRootIsDecorated(False)
        self.proxyView.setAlternatingRowColors(True)
        self.proxyView.setModel(self.proxyModel)
        self.proxyView.setSortingEnabled(True)

        self.sortCaseSensitivityCheckBox = QCheckBox("Case sensitive sorting")
        self.filterCaseSensitivityCheckBox = QCheckBox("Case sensitive filter")

        self.filterPatternLineEdit = QLineEdit()
        self.filterPatternLabel = QLabel("&Filter pattern:")
        self.filterPatternLabel.setBuddy(self.filterPatternLineEdit)

        self.filterSyntaxComboBox = QComboBox()
        self.filterSyntaxComboBox.addItem("Regular expression", QRegExp.RegExp)
        self.filterSyntaxComboBox.addItem("Wildcard", QRegExp.Wildcard)
        self.filterSyntaxComboBox.addItem("Fixed string", QRegExp.FixedString)
        self.filterSyntaxLabel = QLabel("Filter &syntax:")
        self.filterSyntaxLabel.setBuddy(self.filterSyntaxComboBox)

        self.filterColumnComboBox = QComboBox()
        self.filterColumnComboBox.addItem("Subject")
        self.filterColumnComboBox.addItem("Sender")
        self.filterColumnComboBox.addItem("Date")
        self.filterColumnLabel = QLabel("Filter &column:")
        self.filterColumnLabel.setBuddy(self.filterColumnComboBox)

        self.filterPatternLineEdit.textChanged.connect(
            self.filterRegExpChanged)
        self.filterSyntaxComboBox.currentIndexChanged.connect(
            self.filterRegExpChanged)
        self.filterColumnComboBox.currentIndexChanged.connect(
            self.filterColumnChanged)
        self.filterCaseSensitivityCheckBox.toggled.connect(
            self.filterRegExpChanged)
        self.sortCaseSensitivityCheckBox.toggled.connect(self.sortChanged)

        sourceLayout = QHBoxLayout()
        sourceLayout.addWidget(self.sourceView)
        self.sourceGroupBox.setLayout(sourceLayout)

        proxyLayout = QGridLayout()
        proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3)
        proxyLayout.addWidget(self.filterPatternLabel, 1, 0)
        proxyLayout.addWidget(self.filterPatternLineEdit, 1, 1, 1, 2)
        proxyLayout.addWidget(self.filterSyntaxLabel, 2, 0)
        proxyLayout.addWidget(self.filterSyntaxComboBox, 2, 1, 1, 2)
        proxyLayout.addWidget(self.filterColumnLabel, 3, 0)
        proxyLayout.addWidget(self.filterColumnComboBox, 3, 1, 1, 2)
        proxyLayout.addWidget(self.filterCaseSensitivityCheckBox, 4, 0, 1, 2)
        proxyLayout.addWidget(self.sortCaseSensitivityCheckBox, 4, 2)
        self.proxyGroupBox.setLayout(proxyLayout)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.sourceGroupBox)
        mainLayout.addWidget(self.proxyGroupBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Basic Sort/Filter Model")
        self.resize(500, 450)

        self.proxyView.sortByColumn(SENDER, Qt.AscendingOrder)
        self.filterColumnComboBox.setCurrentIndex(SENDER)

        self.filterPatternLineEdit.setText("Andy|Grace")
        self.filterCaseSensitivityCheckBox.setChecked(True)
        self.sortCaseSensitivityCheckBox.setChecked(True)

    def setSourceModel(self, model):
        self.proxyModel.setSourceModel(model)
        self.sourceView.setModel(model)

    def filterRegExpChanged(self):
        syntax_nr = self.filterSyntaxComboBox.itemData(
            self.filterSyntaxComboBox.currentIndex())
        syntax = QRegExp.PatternSyntax(syntax_nr)

        if self.filterCaseSensitivityCheckBox.isChecked():
            caseSensitivity = Qt.CaseSensitive
        else:
            caseSensitivity = Qt.CaseInsensitive

        regExp = QRegExp(self.filterPatternLineEdit.text(), caseSensitivity,
                         syntax)
        self.proxyModel.setFilterRegExp(regExp)

    def filterColumnChanged(self):
        self.proxyModel.setFilterKeyColumn(
            self.filterColumnComboBox.currentIndex())

    def sortChanged(self):
        if self.sortCaseSensitivityCheckBox.isChecked():
            caseSensitivity = Qt.CaseSensitive
        else:
            caseSensitivity = Qt.CaseInsensitive

        self.proxyModel.setSortCaseSensitivity(caseSensitivity)
Пример #29
0
class PcaWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(PcaWidget, self).__init__(parent)

        self.component_combo = QComboBox()
        self.component_combo.addItems([self.tr(f"#{i + 1}") for i in range(3)])
        self.distance_radio = QRadioButton(self.tr("Distance"))
        self.distance_radio.setToolTip(self.tr("Distance from the closest point on selected component"))
        self.project_radio = QRadioButton(self.tr("Projection"))
        self.project_radio.setToolTip(self.tr("Projection onto the selected principal component"))
        self.crossprod_radio = QRadioButton(self.tr("Cross product"))
        self.crossprod_radio.setToolTip(self.tr("Cross product between input and selected component"))
        self.distance_radio.setChecked(True)
        self.last_radio = self.distance_radio
        self.invert_check = QCheckBox(self.tr("Invert"))
        self.invert_check.setToolTip(self.tr("Output bitwise complement"))
        self.equalize_check = QCheckBox(self.tr("Equalize"))
        self.equalize_check.setToolTip(self.tr("Apply histogram equalization"))

        rows, cols, chans = image.shape
        x = np.reshape(image, (rows * cols, chans)).astype(np.float32)
        mu, ev, ew = cv.PCACompute2(x, np.array([]))
        p = np.reshape(cv.PCAProject(x, mu, ev), (rows, cols, chans))
        x0 = image.astype(np.float32) - mu
        self.output = []
        for i, v in enumerate(ev):
            cross = np.cross(x0, v)
            distance = np.linalg.norm(cross, axis=2) / np.linalg.norm(v)
            project = p[:, :, i]
            self.output.extend([norm_mat(distance, to_bgr=True), norm_mat(project, to_bgr=True), norm_img(cross)])

        table_data = [
            [mu[0, 2], mu[0, 1], mu[0, 0]],
            [ev[0, 2], ev[0, 1], ev[0, 0]],
            [ev[1, 2], ev[1, 1], ev[1, 0]],
            [ev[2, 2], ev[2, 1], ev[2, 0]],
            [ew[2, 0], ew[1, 0], ew[0, 0]],
        ]
        table_widget = QTableWidget(5, 4)
        table_widget.setHorizontalHeaderLabels([self.tr("Element"), self.tr("Red"), self.tr("Green"), self.tr("Blue")])
        table_widget.setItem(0, 0, QTableWidgetItem(self.tr("Mean vector")))
        table_widget.setItem(1, 0, QTableWidgetItem(self.tr("Eigenvector 1")))
        table_widget.setItem(2, 0, QTableWidgetItem(self.tr("Eigenvector 2")))
        table_widget.setItem(3, 0, QTableWidgetItem(self.tr("Eigenvector 3")))
        table_widget.setItem(4, 0, QTableWidgetItem(self.tr("Eigenvalues")))
        for i in range(len(table_data)):
            modify_font(table_widget.item(i, 0), bold=True)
            for j in range(len(table_data[i])):
                table_widget.setItem(i, j + 1, QTableWidgetItem(str(table_data[i][j])))
        # item = QTableWidgetItem()
        # item.setBackgroundColor(QColor(mu[0, 2], mu[0, 1], mu[0, 0]))
        # table_widget.setItem(0, 4, item)
        # table_widget.resizeRowsToContents()
        # table_widget.resizeColumnsToContents()
        table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        table_widget.setSelectionMode(QAbstractItemView.SingleSelection)
        table_widget.setMaximumHeight(190)

        self.viewer = ImageViewer(image, image, None)
        self.process()

        self.component_combo.currentIndexChanged.connect(self.process)
        self.distance_radio.clicked.connect(self.process)
        self.project_radio.clicked.connect(self.process)
        self.crossprod_radio.clicked.connect(self.process)
        self.invert_check.stateChanged.connect(self.process)
        self.equalize_check.stateChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Component:")))
        top_layout.addWidget(self.component_combo)
        top_layout.addWidget(QLabel(self.tr("Mode:")))
        top_layout.addWidget(self.distance_radio)
        top_layout.addWidget(self.project_radio)
        top_layout.addWidget(self.crossprod_radio)
        top_layout.addWidget(self.invert_check)
        top_layout.addWidget(self.equalize_check)
        top_layout.addStretch()
        bottom_layout = QHBoxLayout()
        bottom_layout.addWidget(table_widget)

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        main_layout.addLayout(bottom_layout)
        self.setLayout(main_layout)

    def process(self):
        index = 3 * self.component_combo.currentIndex()
        if self.distance_radio.isChecked():
            output = self.output[index]
            self.last_radio = self.distance_radio
        elif self.project_radio.isChecked():
            output = self.output[index + 1]
            self.last_radio = self.project_radio
        elif self.crossprod_radio.isChecked():
            output = self.output[index + 2]
            self.last_radio = self.crossprod_radio
        else:
            self.last_radio.setChecked(True)
            return
        if self.invert_check.isChecked():
            output = cv.bitwise_not(output)
        if self.equalize_check.isChecked():
            output = equalize_img(output)
        self.viewer.update_processed(output)
class QLiberationPreferences(QFrame):
    def __init__(self):
        super(QLiberationPreferences, self).__init__()
        self.saved_game_dir = ""
        self.dcs_install_dir = ""
        self.install_dir_ignore_warning = False

        self.dcs_install_dir = liberation_install.get_dcs_install_directory()
        self.saved_game_dir = liberation_install.get_saved_game_dir()

        self.edit_dcs_install_dir = QLineEdit(self.dcs_install_dir)
        self.edit_saved_game_dir = QLineEdit(self.saved_game_dir)

        self.edit_dcs_install_dir.setMinimumWidth(300)
        self.edit_saved_game_dir.setMinimumWidth(300)

        self.browse_saved_game = QPushButton("Browse...")
        self.browse_saved_game.clicked.connect(self.on_browse_saved_games)
        self.browse_install_dir = QPushButton("Browse...")
        self.browse_install_dir.clicked.connect(
            self.on_browse_installation_dir)
        self.themeSelect = QComboBox()
        [self.themeSelect.addItem(y["themeName"]) for x, y in THEMES.items()]

        self.initUi()

    def initUi(self):
        main_layout = QVBoxLayout()
        layout = QGridLayout()
        layout.addWidget(
            QLabel("<strong>DCS saved game directory:</strong>"),
            0,
            0,
            alignment=Qt.AlignLeft,
        )
        layout.addWidget(self.edit_saved_game_dir,
                         1,
                         0,
                         alignment=Qt.AlignRight)
        layout.addWidget(self.browse_saved_game, 1, 1, alignment=Qt.AlignRight)
        layout.addWidget(
            QLabel("<strong>DCS installation directory:</strong>"),
            2,
            0,
            alignment=Qt.AlignLeft,
        )
        layout.addWidget(self.edit_dcs_install_dir,
                         3,
                         0,
                         alignment=Qt.AlignRight)
        layout.addWidget(self.browse_install_dir,
                         3,
                         1,
                         alignment=Qt.AlignRight)
        layout.addWidget(QLabel("<strong>Theme (Requires Restart)</strong>"),
                         4, 0)
        layout.addWidget(self.themeSelect, 4, 1, alignment=Qt.AlignRight)
        self.themeSelect.setCurrentIndex(get_theme_index())

        main_layout.addLayout(layout)
        main_layout.addStretch()

        self.setLayout(main_layout)

    def on_browse_saved_games(self):
        saved_game_dir = str(
            QFileDialog.getExistingDirectory(
                self, "Select DCS Saved Game Directory"))
        if saved_game_dir:
            self.saved_game_dir = saved_game_dir
            self.edit_saved_game_dir.setText(saved_game_dir)

    def on_browse_installation_dir(self):
        install_dir = str(
            QFileDialog.getExistingDirectory(
                self, "Select DCS Installation Directory"))
        if install_dir:
            self.dcs_install_dir = install_dir
            self.edit_dcs_install_dir.setText(install_dir)

    def apply(self):

        print("Applying changes")
        self.saved_game_dir = self.edit_saved_game_dir.text()
        self.dcs_install_dir = self.edit_dcs_install_dir.text()
        set_theme_index(self.themeSelect.currentIndex())

        if not os.path.isdir(self.saved_game_dir):
            error_dialog = QMessageBox.critical(
                self,
                "Wrong DCS Saved Games directory.",
                self.saved_game_dir + " is not a valid directory",
                QMessageBox.StandardButton.Ok,
            )
            error_dialog.exec_()
            return False

        if self.install_dir_ignore_warning and self.dcs_install_dir == "":
            warning_dialog = QMessageBox.warning(
                self,
                "The DCS Installation directory was not set",
                "You set an empty DCS Installation directory! "
                "<br/><br/>Without this directory, DCS Liberation can not replace the MissionScripting.lua for you and will not work properly. "
                "In this case, you need to edit the MissionScripting.lua yourself. The easiest way to do it is to replace the original file (&lt;dcs_installation_directory&gt;/Scripts/MissionScripting.lua) with the file in dcs-liberation distribution (&lt;dcs_liberation_installation&gt;/resources/scripts/MissionScripting.lua)."
                "<br/><br/>You can find more information on how to manually change this file in the Liberation Wiki (Page: Dedicated Server Guide) on GitHub.</p>"
                "<br/><br/>Are you sure that you want to leave the installation directory empty?"
                "<br/><br/><strong>This is only recommended for expert users!</strong>",
                QMessageBox.StandardButton.Yes,
                QMessageBox.StandardButton.No,
            )
            if warning_dialog == QMessageBox.No:
                return False
        elif not os.path.isdir(self.dcs_install_dir):
            error_dialog = QMessageBox.critical(
                self,
                "Wrong DCS installation directory.",
                self.dcs_install_dir +
                " is not a valid directory. DCS Liberation requires the installation directory to replace the MissionScripting.lua"
                "<br/><br/>If you ignore this Error, DCS Liberation can not work properly and needs your attention. "
                "In this case, you need to edit the MissionScripting.lua yourself. The easiest way to do it is to replace the original file (&lt;dcs_installation_directory&gt;/Scripts/MissionScripting.lua) with the file in dcs-liberation distribution (&lt;dcs_liberation_installation&gt;/resources/scripts/MissionScripting.lua)."
                "<br/><br/>You can find more information on how to manually change this file in the Liberation Wiki (Page: Dedicated Server Guide) on GitHub.</p>"
                "<br/><br/><strong>This is only recommended for expert users!</strong>",
                QMessageBox.StandardButton.Ignore,
                QMessageBox.StandardButton.Ok,
            )
            if error_dialog == QMessageBox.Ignore:
                self.install_dir_ignore_warning = True
            return False
        elif not os.path.isdir(os.path.join(
                self.dcs_install_dir, "Scripts")) and os.path.isfile(
                    os.path.join(self.dcs_install_dir, "bin", "DCS.exe")):
            error_dialog = QMessageBox.critical(
                self,
                "Wrong DCS installation directory.",
                self.dcs_install_dir +
                " is not a valid DCS installation directory",
                QMessageBox.StandardButton.Ok,
            )
            error_dialog.exec_()
            return False

        liberation_install.setup(self.saved_game_dir, self.dcs_install_dir)
        liberation_install.save_config()
        liberation_theme.save_theme_config()
        return True
Пример #31
0
class MonteCarloTab(NewAnalysisTab):
    def __init__(self, parent=None):
        super(MonteCarloTab, self).__init__(parent)
        self.parent: LCAResultsSubTab = parent

        self.layout.addLayout(get_header_layout('Monte Carlo Simulation'))
        self.scenario_label = QLabel("Scenario:")
        self.include_box = QGroupBox("Include uncertainty for:", self)
        grid = QGridLayout()
        self.include_tech = QCheckBox("Technosphere", self)
        self.include_tech.setChecked(True)
        self.include_bio = QCheckBox("Biosphere", self)
        self.include_bio.setChecked(True)
        self.include_cf = QCheckBox("Characterization Factors", self)
        self.include_cf.setChecked(True)
        self.include_parameters = QCheckBox("Parameters", self)
        self.include_parameters.setChecked(True)
        grid.addWidget(self.include_tech, 0, 0)
        grid.addWidget(self.include_bio, 0, 1)
        grid.addWidget(self.include_cf, 1, 0)
        grid.addWidget(self.include_parameters, 1, 1)
        self.include_box.setLayout(grid)

        self.add_MC_ui_elements()

        self.table = LCAResultsTable()
        self.table.table_name = 'MonteCarlo_' + self.parent.cs_name
        self.plot = MonteCarloPlot(self.parent)
        self.plot.hide()
        self.plot.plot_name = 'MonteCarlo_' + self.parent.cs_name
        self.layout.addWidget(self.plot)
        self.export_widget = self.build_export(has_plot=True, has_table=True)
        self.layout.addWidget(self.export_widget)
        self.layout.setAlignment(QtCore.Qt.AlignTop)
        self.connect_signals()

    def connect_signals(self):
        self.button_run.clicked.connect(self.calculate_mc_lca)
        # signals.monte_carlo_ready.connect(self.update_mc)
        # self.combobox_fu.currentIndexChanged.connect(self.update_plot)
        self.combobox_methods.currentIndexChanged.connect(
            # ignore the index and send the cs_name instead
            lambda x: self.update_mc(cs_name=self.parent.cs_name))

        # signals
        # self.radio_button_biosphere.clicked.connect(self.button_clicked)
        # self.radio_button_technosphere.clicked.connect(self.button_clicked)

        if self.using_presamples:
            self.scenario_box.currentIndexChanged.connect(
                self.parent.update_scenario_data)
            self.parent.update_scenario_box_index.connect(
                lambda index: self.set_combobox_index(self.scenario_box, index
                                                      ))

    def add_MC_ui_elements(self):
        layout_mc = QVBoxLayout()

        # H-LAYOUT start simulation
        self.button_run = QPushButton('Run Simulation')
        self.label_iterations = QLabel('Iterations:')
        self.iterations = QLineEdit('10')
        self.iterations.setFixedWidth(40)
        self.iterations.setValidator(QtGui.QIntValidator(1, 1000))
        self.label_seed = QLabel('Random seed:')
        self.label_seed.setToolTip(
            'Seed value (integer) for the random number generator. '
            'Use this for reproducible samples.')
        self.seed = QLineEdit('')
        self.seed.setFixedWidth(30)

        self.hlayout_run = QHBoxLayout()
        self.hlayout_run.addWidget(self.scenario_label)
        self.hlayout_run.addWidget(self.scenario_box)
        self.hlayout_run.addWidget(self.button_run)
        self.hlayout_run.addWidget(self.label_iterations)
        self.hlayout_run.addWidget(self.iterations)
        self.hlayout_run.addWidget(self.label_seed)
        self.hlayout_run.addWidget(self.seed)
        self.hlayout_run.addWidget(self.include_box)
        self.hlayout_run.addStretch(1)
        layout_mc.addLayout(self.hlayout_run)

        # self.label_running = QLabel('Running a Monte Carlo simulation. Please allow some time for this. '
        #                             'Please do not run another simulation at the same time.')
        # self.layout_mc.addWidget(self.label_running)
        # self.label_running.hide()

        # # buttons for all FUs or for all methods
        # self.radio_button_all_fu = QRadioButton("For all functional units")
        # self.radio_button_all_methods = QRadioButton("Technosphere flows")
        #
        # self.radio_button_biosphere.setChecked(True)
        # self.radio_button_technosphere.setChecked(False)
        #
        # self.label_for_all_fu = QLabel('For all functional units')
        # self.combobox_fu = QRadioButton()
        # self.hlayout_fu = QHBoxLayout()

        # FU selection
        # self.label_fu = QLabel('Choose functional unit')
        # self.combobox_fu = QComboBox()
        # self.hlayout_fu = QHBoxLayout()
        #
        # self.hlayout_fu.addWidget(self.label_fu)
        # self.hlayout_fu.addWidget(self.combobox_fu)
        # self.hlayout_fu.addStretch()
        # self.layout_mc.addLayout(self.hlayout_fu)

        # method selection
        self.method_selection_widget = QWidget()
        self.label_methods = QLabel('Choose LCIA method')
        self.combobox_methods = QComboBox()
        self.hlayout_methods = QHBoxLayout()

        self.hlayout_methods.addWidget(self.label_methods)
        self.hlayout_methods.addWidget(self.combobox_methods)
        self.hlayout_methods.addStretch()
        self.method_selection_widget.setLayout(self.hlayout_methods)

        layout_mc.addWidget(self.method_selection_widget)
        self.method_selection_widget.hide()

        self.layout.addLayout(layout_mc)

    def build_export(self,
                     has_table: bool = True,
                     has_plot: bool = True) -> QWidget:
        """Construct the export layout but set it into a widget because we
         want to hide it."""
        export_layout = super().build_export(has_table, has_plot)
        export_widget = QWidget()
        export_widget.setLayout(export_layout)
        # Hide widget until MC is calculated
        export_widget.hide()
        return export_widget

    @QtCore.Slot(name="calculateMcLca")
    def calculate_mc_lca(self):
        self.method_selection_widget.hide()
        self.plot.hide()
        self.export_widget.hide()

        iterations = int(self.iterations.text())
        seed = None
        if self.seed.text():
            print('SEED: ', self.seed.text())
            try:
                seed = int(self.seed.text())
            except ValueError:
                traceback.print_exc()
                QMessageBox.warning(
                    self, 'Warning',
                    'Seed value must be an integer number or left empty.')
                self.seed.setText('')
                return
        includes = {
            "technosphere": self.include_tech.isChecked(),
            "biosphere": self.include_bio.isChecked(),
            "cf": self.include_cf.isChecked(),
            "parameters": self.include_parameters.isChecked(),
        }

        try:
            self.parent.mc.calculate(iterations=iterations,
                                     seed=seed,
                                     **includes)
            self.update_mc()
        except InvalidParamsError as e:  # This can occur if uncertainty data is missing or otherwise broken
            # print(e)
            traceback.print_exc()
            QMessageBox.warning(self,
                                'Could not perform Monte Carlo simulation',
                                str(e))

        # a threaded way for this - unfortunatley this crashes as:
        # pypardsio_solver is used for the 'spsolve' and 'factorized' functions. Python crashes on windows if multiple
        # instances of PyPardisoSolver make calls to the Pardiso library
        # worker_thread = WorkerThread()
        # print('Created local worker_thread')
        # worker_thread.set_mc(self.parent.mc, iterations=iterations)
        # print('Passed object to thread.')
        # worker_thread.start()
        # self.label_running.show()

        #

        # thread = NewCSMCThread() #self.parent.mc
        # thread.calculation_finished.connect(
        #     lambda x: print('Calculation finished.'))
        # thread.start()

        # # give us a thread and start it
        # thread = QtCore.QThread()
        # thread.start()
        #
        # # create a worker and move it to our extra thread
        # worker = Worker()
        # worker.moveToThread(thread)

        # self.parent.mct.start()
        # self.parent.mct.run(iterations=iterations)
        # self.parent.mct.finished()

        # objThread = QtCore.QThread()
        # obj = QObjectMC()  # self.parent.cs_name
        # obj.moveToThread(objThread)
        # obj.finished.connect(objThread.quit)
        # objThread.started.connect(obj.long_running)
        # # objThread.finished.connect(app.exit)
        # objThread.finished.connect(
        #     lambda x: print('Finished Thread!')
        # )
        # objThread.start()

        # objThread = QtCore.QThread()
        # obj = SomeObject()
        # obj.moveToThread(objThread)
        # obj.finished.connect(objThread.quit)
        # objThread.started.connect(obj.long_running)
        # objThread.finished.connect(
        #     lambda x: print('Finished Thread!')
        # )
        # objThread.start()

        # self.method_selection_widget.show()
        # self.plot.show()
        # self.export_widget.show()

    def configure_scenario(self):
        super().configure_scenario()
        self.scenario_label.setVisible(self.using_presamples)

    def update_tab(self):
        self.update_combobox(self.combobox_methods,
                             [str(m) for m in self.parent.mc.methods])
        # self.update_combobox(self.combobox_methods, [str(m) for m in self.parent.mct.mc.methods])

    def update_mc(self, cs_name=None):
        # act = self.combobox_fu.currentText()
        # activity_index = self.combobox_fu.currentIndex()
        # act_key = self.parent.mc.activity_keys[activity_index]
        # if cs_name != self.parent.cs_name:  # relevant if several CS are open at the same time
        #     return

        # self.label_running.hide()
        self.method_selection_widget.show()
        self.export_widget.show()

        method_index = self.combobox_methods.currentIndex()
        method = self.parent.mc.methods[method_index]

        # data = self.parent.mc.get_results_by(act_key=act_key, method=method)
        self.df = self.parent.mc.get_results_dataframe(method=method)

        self.update_table()
        self.update_plot(method=method)
        filename = '_'.join([
            str(x)
            for x in [self.parent.cs_name, 'Monte Carlo results',
                      str(method)]
        ])
        self.plot.plot_name, self.table.table_name = filename, filename

    def update_plot(self, method):
        idx = self.layout.indexOf(self.plot)
        self.plot.figure.clf()
        self.plot.deleteLater()
        self.plot = MonteCarloPlot(self.parent)
        self.layout.insertWidget(idx, self.plot)
        self.plot.plot(self.df, method=method)
        self.plot.show()
        if self.layout.parentWidget():
            self.layout.parentWidget().updateGeometry()

    def update_table(self):
        self.table.sync(self.df)
Пример #32
0
class ExportFileDialog(QFileDialog):
    """
    Create a custom Export-File Dialog with options like BOM etc.
    """

    def __init__(self,*args,**kwargs):
        super(ExportFileDialog,self).__init__(*args,**kwargs)

        self.mainWindow = self.parent()
        self.setWindowTitle("Export nodes to CSV")
        self.setAcceptMode(QFileDialog.AcceptSave)
        self.setOption(QFileDialog.DontUseNativeDialog)
        #self.setFilter("CSV Files (*.csv)")
        self.setDefaultSuffix("csv")

        self.optionBOM = QCheckBox("Use a BOM",self)
        self.optionBOM.setCheckState(Qt.CheckState.Checked)

        self.optionLinebreaks = QCheckBox("Remove line breaks",self)
        self.optionLinebreaks.setCheckState(Qt.CheckState.Checked)

        self.optionSeparator = QComboBox(self)
        self.optionSeparator.insertItems(0, [";","\\t",","])
        self.optionSeparator.setEditable(True)

        #self.optionLinebreaks.setCheckState(Qt.CheckState.Checked)

        self.optionWide = QCheckBox("Convert to wide format (experimental feature)",self)
        self.optionWide.setCheckState(Qt.CheckState.Unchecked)

        # if none or all are selected, export all
        # if one or more are selected, export selective
        self.optionAll = QComboBox(self)
        self.optionAll.insertItems(0, ['All nodes (faster for large datasets, ordered by internal ID)','Selected nodes (ordered like shown in nodes view)'])
        if self.mainWindow.tree.noneOrAllSelected():
            self.optionAll.setCurrentIndex(0)
        else:
            self.optionAll.setCurrentIndex(1)

        layout = self.layout()
        row = layout.rowCount()
        layout.addWidget(QLabel('Options'),row,0)

        options = QHBoxLayout()
        options.addWidget(self.optionBOM)
        options.addWidget(self.optionLinebreaks)
        options.addWidget(QLabel('Separator'))
        options.addWidget(self.optionSeparator)
        options.addStretch(1)

        layout.addLayout(options,row,1,1,2)

        layout.addWidget(QLabel('Post processing'),row+1,0)
        layout.addWidget(self.optionWide,row+1,1,1,2)

        layout.addWidget(QLabel('Export mode'),row+2,0)
        layout.addWidget(self.optionAll,row+2,1,1,2)
        self.setLayout(layout)

        if self.exec_():

            if os.path.isfile(self.selectedFiles()[0]):
                os.remove(self.selectedFiles()[0])
            output = open(self.selectedFiles()[0], 'w', newline='', encoding='utf8')
            if self.optionBOM.isChecked() and not self.optionWide.isChecked():
                output.write('\ufeff')

            try:
                if self.optionAll.currentIndex() == 0:
                    self.exportAllNodes(output)
                else:
                    self.exportSelectedNodes(output)
            finally:
                output.close()

            if self.optionWide.isChecked():
                self.convertToWideFormat(self.selectedFiles()[0])


    def exportSelectedNodes(self,output):
        progress = ProgressBar("Exporting data...", self.mainWindow)

        #indexes = self.mainWindow.tree.selectionModel().selectedRows()
        #if child nodes should be exported as well, uncomment this line an comment the previous one
        indexes = self.mainWindow.tree.selectedIndexesAndChildren()
        progress.setMaximum(len(indexes))

        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output, delimiter=delimiter, quotechar='"', quoting=csv.QUOTE_ALL, doublequote=True,
                                lineterminator='\r\n')


            #headers
            row = [str(val) for val in self.mainWindow.tree.treemodel.getRowHeader()]
            if self.optionLinebreaks.isChecked():
                row = [val.replace('\n', ' ').replace('\r',' ') for val in row]

            writer.writerow(row)

            #rows
            for no in range(len(indexes)):
                if progress.wasCanceled:
                    break

                row = [str(val) for val in self.mainWindow.tree.treemodel.getRowData(indexes[no])]
                if self.optionLinebreaks.isChecked():
                    row = [val.replace('\n', ' ').replace('\r',' ') for val in row]

                writer.writerow(row)

                progress.step()

        finally:
            progress.close()


    def exportAllNodes(self,output):
        progress = ProgressBar("Exporting data...", self.mainWindow)
        progress.setMaximum(Node.query.count())


        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output, delimiter=delimiter, quotechar='"', quoting=csv.QUOTE_ALL, doublequote=True,
                                lineterminator='\r\n')

            #headers
            row = ["level", "id", "parent_id", "object_id", "object_type", "query_status", "query_time",
                   "query_type"]
            for key in self.mainWindow.tree.treemodel.customcolumns:
                row.append(key)
            if self.optionLinebreaks.isChecked():
                row = [val.replace('\n', ' ').replace('\r',' ') for val in row]

            writer.writerow(row)

            #rows
            page = 0

            while True:
                allnodes = Node.query.offset(page * 5000).limit(5000)
                if allnodes.count() == 0:
                    break
                for node in allnodes:
                    if progress.wasCanceled:
                        break
                    row = [node.level, node.id, node.parent_id, node.objectid, node.objecttype,
                           node.querystatus, node.querytime, node.querytype]
                    for key in self.mainWindow.tree.treemodel.customcolumns:
                        row.append(node.getResponseValue(key))

                    if self.optionLinebreaks.isChecked():
                        row = [str(val).replace('\n', ' ').replace('\r',' ') for val in row]

                    writer.writerow(row)
                    # step the Bar
                    progress.step()
                if progress.wasCanceled:
                    break
                else:
                    page += 1

        finally:
            progress.close()

    def convertToWideFormat(self,filename):
        progress = ProgressBar("Converting data...", self.mainWindow)
        try:
            #Separate levels
            def flattenTable(fulltable,levelcol,idcol,parentidcol,countchildren,removeempty):
                fulltable[[levelcol]] = fulltable[[levelcol]].astype(int)

                levels = dict(list(fulltable.groupby(levelcol)))
                minlevel = fulltable.level.min()
                for level, data in sorted(levels.items()):
                    #First level is the starting point for the following merges
                    if level == minlevel:
                        #data = data[[idcol,'object_id','object_type']]
                        data = data.add_prefix('level_{}-'.format(level))
                        flattable = data
                    else:
                        #Aggregate object types and join them
                        for col_countchildren in countchildren:
                            children = data[parentidcol].groupby([data[parentidcol],data[col_countchildren]]).count()
                            children = children.unstack(col_countchildren)
                            children['total'] = children.sum(axis=1)
                            children = children.add_prefix('level_{}-children-{}-'.format(level-1,col_countchildren))

                            leftkey = 'level_{}-id'.format(level-1)
                            flattable = merge(flattable,children,how='left',left_on=leftkey,right_index=True)
                            flattable[children.columns.values.tolist()] = flattable[children.columns.values.tolist()].fillna(0).astype(int)

                        #Join data
                        data['childnumber'] = data.groupby(parentidcol).cumcount()
                        leftkey = 'level_{}-{}'.format(level-1,idcol)
                        rightkey = 'level_{}-{}'.format(level,parentidcol)
                        data = data.drop([levelcol],axis=1)
                        data = data.add_prefix('level_{}-'.format(level))
                        flattable = merge(flattable,data,how="outer",left_on=leftkey,right_on=rightkey)

                if removeempty:
                    flattable = flattable.dropna(axis=1,how='all')
                return flattable

            try:
                #delimiter
                delimiter = self.optionSeparator.currentText()
                delimiter = delimiter.encode('utf-8').decode('unicode_escape')

                #open
                data = read_csv(filename, sep=delimiter,encoding='utf-8',dtype=str)

                #convert
                newdata = flattenTable(data,'level','id','parent_id',['object_type','query_status','query_type'],False)


                #save
                outfile = open(filename, 'w',newline='',encoding='utf8')
                try:
                    if self.optionBOM.isChecked():
                        outfile.write('\ufeff') #UTF8 BOM
                    newdata.to_csv(outfile,sep=delimiter,index=False,encoding="utf-8")
                finally:
                    outfile.close()
            except Exception as e:
                self.mainWindow.logmessage(e)
        finally:
            progress.close()