class OptionsPanel(QWidget): """Supported API. OptionsPanel is a container for single-use (not savable) Options""" def __init__(self, parent=None, *, sorting=True, scrolled=True, contents_margins=None): """sorting: False; options shown in order added True: options sorted alphabetically by name func: options sorted based on the provided key function """ QWidget.__init__(self, parent) self._layout = QVBoxLayout() if contents_margins is not None: self._layout.setContentsMargins(*contents_margins) if scrolled: sublayout = QVBoxLayout() sublayout.setContentsMargins(3, 0, 3, 2) self.setLayout(sublayout) scroller = QScrollArea() scroller.setWidgetResizable(True) sublayout.addWidget(scroller) scrolled_area = QWidget() scroller.setWidget(scrolled_area) scrolled_area.setLayout(self._layout) else: self.setLayout(self._layout) self._sorting = sorting self._options = [] self._option_groups = [] self._layout.setSizeConstraint(self._layout.SetMinAndMaxSize) self._form = QFormLayout() self._form.setSizeConstraint(self._form.SetMinAndMaxSize) self._form.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self._form.setVerticalSpacing(1) from PyQt5.QtCore import Qt # None of the below seem to have an effect on the Mac... #self._form.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter) #self._form.setFormAlignment(Qt.AlignLeft | Qt.AlignVCenter) # if we wanted to force the form contents to upper left... #self._form.setFormAlignment(Qt.AlignLeft | Qt.AlignTop) self._layout.addLayout(self._form) def add_option(self, option): """Supported API. Add an option (instance of chimerax.ui.options.Option).""" if self._sorting is False: insert_row = len(self._options) else: if self._sorting is True: test = lambda o1, o2: o1.name < o2.name else: test = lambda o1, o2: self._sorting(o1) < self._sorting(o2) for insert_row in range(len(self._options)): if test(option, self._options[insert_row]): break else: insert_row = len(self._options) self._form.insertRow(insert_row, option.name, option.widget) self._options.insert(insert_row, option) if option.balloon: self._form.itemAt(insert_row, QFormLayout.LabelRole).widget().setToolTip( option.balloon) def add_option_group(self, group_label=None, checked=None, group_alignment=None, **kw): if group_label is None: grouping_widget = QWidget() else: grouping_widget = QGroupBox(group_label) grouping_widget.setContentsMargins( 1, grouping_widget.contentsMargins().top() // 2, 1, 1) if checked is not None: grouping_widget.setCheckable(True) grouping_widget.setChecked(checked) add_kw = {} if group_alignment is None else { 'alignment': group_alignment } self._layout.addWidget(grouping_widget, **add_kw) suboptions = OptionsPanel(scrolled=False, **kw) self._option_groups.append(suboptions) return grouping_widget, suboptions def change_label_for_option(self, option, new_label): self._form.labelForField(option.widget).setText(new_label) def options(self): all_options = self._options[:] for grp in self._option_groups: # an option group can have further subgroups, so call options() all_options.extend(grp.options()) return all_options def sizeHint(self): from PyQt5.QtCore import QSize form_size = self._form.minimumSize() return QSize(min(form_size.width(), 800), min(form_size.height(), 800))
class Tabs(QTabWidget): def __init__(self): super().__init__() self.tab1 = QWidget() self.tab2 = QWidget() self.tab3 = QWidget() self.tab4 = QWidget() self.tab1UI() self.tab2UI() self.tab3UI() self.tab4UI() self.addTab(self.tab1, "Mouse") self.addTab(self.tab2, "Keyboard") self.addTab(self.tab3, "Screen") self.addTab(self.tab4, "Settings") def tab1UI(self): self.stackedwidget = QStackedWidget() self.moveToWid = QWidget() self.moveRelWid = QWidget() self.dragToWid = QWidget() self.dragRelWid = QWidget() self.clickToPositionWid = QWidget() self.clickWid = QWidget() self.scrollWid = QWidget() self.moveToLay() self.moveRelLay() self.dragToLay() self.dragRelLay() self.clickToPositionLay() self.clickLay() self.scrollLay() self.stackedwidget.addWidget(self.moveToWid) self.stackedwidget.addWidget(self.moveRelWid) self.stackedwidget.addWidget(self.dragToWid) self.stackedwidget.addWidget(self.dragRelWid) self.stackedwidget.addWidget(self.clickToPositionWid) self.stackedwidget.addWidget(self.clickWid) self.stackedwidget.addWidget(self.scrollWid) v_box = QVBoxLayout() MP_form = QFormLayout() #MOUSE POSITION self.mousepositionButton = QPushButton("Get mouse position {}".format( hotkeysList[0])) self.mousepositionLabel = QLabel() self.mousepositionButton.clicked.connect(self.getMousePosition) self.mousepositionButton.setShortcut("Ctrl+P") self.shortcut = QShortcut(QKeySequence("Ctrl+O"), self) self.shortcut.activated.connect(self.getMousePosition) #COMBOBOX self.comboBox = QComboBox() self.comboBox.addItems([ "Move To", "Move Relative", "Drag To", "Drag Relative", "Click To", "Click", "Scroll" ]) MP_form.addRow(self.mousepositionButton, self.mousepositionLabel) MP_form.addRow(self.comboBox) v_box.addLayout(MP_form) v_box.addWidget(self.stackedwidget) self.tab1.setLayout(v_box) self.comboBox.currentIndexChanged.connect(self.cbApply) def cbApply(self, q): self.stackedwidget.setCurrentIndex(q) def moveToLay(self): self.onlyInt = QIntValidator() self.moveToX = QLineEdit("0") self.moveToY = QLineEdit("0") self.moveToDuration = QLineEdit("0") self.moveToAddButton = QPushButton("Add to List") self.moveToX.setValidator(self.onlyInt) self.moveToY.setValidator(self.onlyInt) self.moveToDuration.setValidator(self.onlyInt) moveToForm = QFormLayout() moveToForm.addRow("X coordinate :", self.moveToX) moveToForm.addRow("Y coordinate :", self.moveToY) moveToForm.addRow("Duration :", self.moveToDuration) moveToForm.addRow(self.moveToAddButton) self.moveToWid.setLayout(moveToForm) self.moveToAddButton.clicked.connect(self.moveToDo) def moveRelLay(self): self.onlyInt = QIntValidator() self.moveRelX = QLineEdit("0") self.moveRelY = QLineEdit("0") self.moveRelDuration = QLineEdit("0") self.moveRelAddButton = QPushButton("Add to List") self.moveRelX.setValidator(self.onlyInt) self.moveRelY.setValidator(self.onlyInt) self.moveRelDuration.setValidator(self.onlyInt) moveRelForm = QFormLayout() moveRelForm.addRow("Relative X :", self.moveRelX) moveRelForm.addRow("Relative Y :", self.moveRelY) moveRelForm.addRow("Duration :", self.moveRelDuration) moveRelForm.addRow(self.moveRelAddButton) self.moveRelWid.setLayout(moveRelForm) self.moveRelAddButton.clicked.connect(self.moveRelDo) def dragToLay(self): self.onlyInt = QIntValidator() self.dragToX = QLineEdit("0") self.dragToY = QLineEdit("0") self.dragToDuration = QLineEdit("0") self.dragToAddButton = QPushButton("Add to List") self.dragToX.setValidator(self.onlyInt) self.dragToY.setValidator(self.onlyInt) self.dragToDuration.setValidator(self.onlyInt) dragToForm = QFormLayout() dragToForm.addRow("X coordinate :", self.dragToX) dragToForm.addRow("Y coordinate :", self.dragToY) dragToForm.addRow("Duration :", self.dragToDuration) dragToForm.addRow(self.dragToAddButton) self.dragToWid.setLayout(dragToForm) self.dragToAddButton.clicked.connect(self.dragToDo) def dragRelLay(self): self.onlyInt = QIntValidator() self.dragRelX = QLineEdit("0") self.dragRelY = QLineEdit("0") self.dragRelDuration = QLineEdit("0") self.dragRelAddButton = QPushButton("Add to List") self.dragRelX.setValidator(self.onlyInt) self.dragRelY.setValidator(self.onlyInt) self.dragRelDuration.setValidator(self.onlyInt) dragRelForm = QFormLayout() dragRelForm.addRow("Relative X :", self.dragRelX) dragRelForm.addRow("Relative Y :", self.dragRelY) dragRelForm.addRow("Duration :", self.dragRelDuration) dragRelForm.addRow(self.dragRelAddButton) self.dragRelWid.setLayout(dragRelForm) self.dragRelAddButton.clicked.connect(self.dragRelDo) def clickToPositionLay(self): self.onlyInt = QIntValidator() self.clickToPositionX = QLineEdit("0") self.clickToPositionY = QLineEdit("0") self.clickToPositionClicks = QLineEdit("1") self.clickToPositionInterval = QLineEdit("0") self.clickToPositionDuration = QLineEdit("0") self.clickToPositionX.setValidator(self.onlyInt) self.clickToPositionY.setValidator(self.onlyInt) self.clickToPositionClicks.setValidator(self.onlyInt) self.clickToPositionInterval.setValidator(self.onlyInt) self.clickToPositionDuration.setValidator(self.onlyInt) self.clickToPositionR1 = QRadioButton("Left") self.clickToPositionR2 = QRadioButton("Middle") self.clickToPositionR3 = QRadioButton("Right") self.clickToPositionAddButton = QPushButton("Add to List") clickToPositionH_box = QHBoxLayout() clickToPositionH_box.addWidget(self.clickToPositionR1) clickToPositionH_box.addWidget(self.clickToPositionR2) clickToPositionH_box.addWidget(self.clickToPositionR3) clickToPositionForm = QFormLayout() clickToPositionForm.addRow("Button :", clickToPositionH_box) clickToPositionForm.addRow("X coordinate :", self.clickToPositionX) clickToPositionForm.addRow("Y coordinate :", self.clickToPositionY) clickToPositionForm.addRow("Clicks (times) :", self.clickToPositionClicks) clickToPositionForm.addRow("Interval :", self.clickToPositionInterval) clickToPositionForm.addRow("Duration :", self.clickToPositionDuration) clickToPositionForm.addRow(self.clickToPositionAddButton) self.clickToPositionWid.setLayout(clickToPositionForm) self.clickToPositionAddButton.clicked.connect(self.clickToPositionDo) def clickLay(self): self.onlyInt = QIntValidator() self.clickClicks = QLineEdit("1") self.clickInterval = QLineEdit("0") self.clickDuration = QLineEdit("0") self.clickClicks.setValidator(self.onlyInt) self.clickInterval.setValidator(self.onlyInt) self.clickDuration.setValidator(self.onlyInt) self.clickR1 = QRadioButton("Left") self.clickR2 = QRadioButton("Middle") self.clickR3 = QRadioButton("Right") self.clickAddButton = QPushButton("Add to List") clickH_box = QHBoxLayout() clickH_box.addWidget(self.clickR1) clickH_box.addWidget(self.clickR2) clickH_box.addWidget(self.clickR3) clickForm = QFormLayout() clickForm.addRow("Button :", clickH_box) clickForm.addRow("Clicks (times) :", self.clickClicks) clickForm.addRow("Interval :", self.clickInterval) clickForm.addRow("Duration :", self.clickDuration) clickForm.addRow(self.clickAddButton) self.clickWid.setLayout(clickForm) self.clickAddButton.clicked.connect(self.clickDo) def scrollLay(self): self.onlyInt = QIntValidator() self.scrollTimes = QLineEdit("1") self.scrollTimes.setValidator(self.onlyInt) self.scrollAddButton = QPushButton("Add to List") scrollForm = QFormLayout() scrollForm.addRow("Times :", self.scrollTimes) scrollForm.addRow("Times :", self.scrollAddButton) self.scrollWid.setLayout(scrollForm) self.scrollAddButton.clicked.connect(self.scrollDo) def getMousePosition(self): x, y = pyautogui.position() x, y = str(x), str(y) self.mousepositionLabel.setText("{},{}".format(x, y)) self.clickToPositionX.setText(x) self.clickToPositionY.setText(y) self.moveToX.setText(x) self.moveToY.setText(y) self.dragToX.setText(x) self.dragToY.setText(y) def moveToDo(self): item = [ "Move To", "X Coordinate", self.moveToX.text(), "Y Coordinate", self.moveToY.text(), "Duration", self.moveToDuration.text() ] add(item) def moveRelDo(self): item = [ "Move Relative", "Relative X", self.moveRelX.text(), "Relative Y", self.moveRelY.text(), "Duration", self.moveRelDuration.text() ] add(item) def dragToDo(self): item = [ "Drag To", "X Coordinate", self.dragToX.text(), "Y Coordinate", self.dragToY.text(), "Duration", self.dragToDuration.text() ] add(item) def dragRelDo(self): item = [ "Drag Relative", "Relative X", self.dragRelX.text(), "Relative Y", self.dragRelY.text(), "Duration", self.dragRelDuration.text() ] add(item) def clickToPositionDo(self): clickSelected = "left" if self.clickToPositionR2.isChecked(): clickSelected = "middle" if self.clickToPositionR3.isChecked(): clickSelected = "right" item = [ "Click To", "X Coordinate", self.clickToPositionX.text(), "Y Coordinate", self.clickToPositionY.text(), "Button", clickSelected, "Clicks", self.clickToPositionClicks.text(), "Interval", self.clickToPositionInterval.text(), "Duration", self.clickToPositionDuration.text() ] add(item) def clickDo(self): clickSelected = "left" if self.clickR2.isChecked(): clickSelected = "middle" if self.clickR3.isChecked(): clickSelected = "right" item = [ "Click", "Button", clickSelected, "Clicks", self.clickClicks.text(), "Interval", self.clickInterval.text(), "Duration", self.clickDuration.text() ] add(item) def scrollDo(self): item = ["Scroll", "Times", self.scrollTimes.text()] add(item) def tab2UI(self): self.stackedwidget2 = QStackedWidget() self.writeWid = QWidget() self.pressWid = QWidget() self.hotkeyWid = QWidget() self.keyDownUpWid = QWidget() self.writeLay() self.pressLay() self.hotkeyLay() self.keyDownUpLay() self.stackedwidget2.addWidget(self.writeWid) self.stackedwidget2.addWidget(self.pressWid) self.stackedwidget2.addWidget(self.hotkeyWid) self.stackedwidget2.addWidget(self.keyDownUpWid) v_box2 = QVBoxLayout() #COMBOBOX self.comboBox2 = QComboBox() self.comboBox2.addItems(["Write", "Press", "Hotkey", "Key Down/Up"]) v_box2.addWidget(self.comboBox2) v_box2.addWidget(self.stackedwidget2) self.tab2.setLayout(v_box2) self.comboBox2.currentIndexChanged.connect(self.cbApply2) def cbApply2(self, q): self.stackedwidget2.setCurrentIndex(q) def writeLay(self): onlyInt = QIntValidator() self.writeText = QPlainTextEdit() self.writeInterval = QLineEdit("0") writeButton = QPushButton("Add to List") self.writeInterval.setValidator(onlyInt) writeForm = QFormLayout() writeForm.addRow("Text :", self.writeText) writeForm.addRow("Interval :", self.writeInterval) writeForm.addRow(writeButton) self.writeWid.setLayout(writeForm) writeButton.clicked.connect(self.writeDo) def writeDo(self): item = [ "Write", "Interval", self.writeInterval.text(), "Text", self.writeText.toPlainText() ] add(item) def pressLay(self): onlyInt = QIntValidator() nospace = QRegExpValidator(QRegExp("[^ ]+")) self.pressText = QLineEdit() self.pressInterval = QLineEdit("0") self.pressPresses = QLineEdit("1") pressButton = QPushButton("Add to List") self.pressInterval.setValidator(onlyInt) self.pressPresses.setValidator(onlyInt) self.pressText.setValidator(nospace) pressInfo = QLabel( "You can write enter, capslock ve space...\nLook keys.txt for details." ) pressForm = QFormLayout() pressForm.addRow(pressInfo) pressForm.addRow("Key :", self.pressText) pressForm.addRow("Presses :", self.pressPresses) pressForm.addRow("Interval :", self.pressInterval) pressForm.addRow(pressButton) self.pressWid.setLayout(pressForm) pressButton.clicked.connect(self.pressDo) def pressDo(self): item = [ "Press", "Presses", self.pressPresses.text(), "Interval", self.pressInterval.text(), "Key", self.pressText.text() ] add(item) def hotkeyLay(self): hotkeyInfo = QLabel( "If you want ctrl+c write ctrl c\nshift+ctrl+u = shift ctrl u \nalt+f4 = alt f4" ) self.hotkeyText = QLineEdit() hotkeyButton = QPushButton("Add to List") hotkeyForm = QFormLayout() hotkeyForm.addRow(hotkeyInfo) hotkeyForm.addRow("Hotkey :", self.hotkeyText) hotkeyForm.addRow(hotkeyButton) self.hotkeyWid.setLayout(hotkeyForm) hotkeyButton.clicked.connect(self.hotkeyDo) def hotkeyDo(self): item = ["Hotkey", "Hotkey", self.hotkeyText.text()] add(item) def keyDownUpLay(self): nospace = QRegExpValidator(QRegExp("[^ ]+")) self.keyDownUpText = QLineEdit() self.keyDownUpText.setValidator(nospace) self.keyDownUpR1 = QRadioButton("Down") self.keyDownUpR2 = QRadioButton("Up") keyDownUpButton = QPushButton("Add to List") keyDownUpInfo = QLabel("Down will press key.\nUp will leave key.") keyDownUpForm = QFormLayout() keyDownUpHBox = QHBoxLayout() keyDownUpHBox.addWidget(self.keyDownUpR1) keyDownUpHBox.addWidget(self.keyDownUpR2) keyDownUpForm.addRow(keyDownUpInfo) keyDownUpForm.addRow(keyDownUpHBox) keyDownUpForm.addRow("Key :", self.keyDownUpText) keyDownUpForm.addRow(keyDownUpButton) self.keyDownUpWid.setLayout(keyDownUpForm) keyDownUpButton.clicked.connect(self.keyDownUpDo) def keyDownUpDo(self): radio = "Key Down" if self.keyDownUpR2.isChecked(): radio = "Key Up" item = [radio, "Key", self.keyDownUpText.text()] add(item) def tab3UI(self): self.stackedwidget3 = QStackedWidget() self.screenshotWid = QWidget() self.findImageWid = QWidget() self.screenshotLay() self.findImageLay() self.stackedwidget3.addWidget(self.screenshotWid) self.stackedwidget3.addWidget(self.findImageWid) v_box3 = QVBoxLayout() #COMBOBOX self.comboBox3 = QComboBox() self.comboBox3.addItems(["Screenshot", "Find Image on Screen"]) v_box3.addWidget(self.comboBox3) v_box3.addWidget(self.stackedwidget3) self.tab3.setLayout(v_box3) self.comboBox3.currentIndexChanged.connect(self.cbApply3) def cbApply3(self, q): self.stackedwidget3.setCurrentIndex(q) def screenshotLay(self): self.screenshotPath = QLineEdit(os.getcwd()) self.screenshotPath.setReadOnly(True) self.screenshotFile = QLineEdit() changePathButton = QPushButton("Change Path") screenshotButton = QPushButton("Add to List") self.screenshotR1 = QRadioButton("Yes") self.screenshotR2 = QRadioButton("No") screenshotHBox = QHBoxLayout() screenshotHBox.addWidget(self.screenshotR1) screenshotHBox.addWidget(self.screenshotR2) screenshotForm = QFormLayout() screenshotForm.addRow("Save Path :", self.screenshotPath) screenshotForm.addRow(changePathButton) screenshotForm.addRow("File Name :", self.screenshotFile) screenshotForm.addRow("Overwrite :", screenshotHBox) screenshotForm.addRow(screenshotButton) self.screenshotWid.setLayout(screenshotForm) changePathButton.clicked.connect(self.changePath) screenshotButton.clicked.connect(self.screenshotDo) def changePath(self): dir_ = QFileDialog.getExistingDirectory(self, 'Select a folder:', os.getcwd(), QFileDialog.ShowDirsOnly) self.screenshotPath.setText(dir_) def screenshotDo(self): if self.screenshotFile.text() == "": QMessageBox.warning(self, 'Error!', "Please enter a file name.", QMessageBox.Ok) else: radio = "yes" if self.screenshotR2.isChecked(): radio = "no" item = [ "Screenshot", "Overwrite", radio, "Dir Path", self.screenshotPath.text(), "File Name", self.screenshotFile.text() ] add(item) def findImageLay(self): self.findImagePath = QLineEdit() self.findImagePath.setReadOnly(True) self.findImageInfo = QLabel("Low screen resolution for fast search.") findImageButton = QPushButton("Select a Image") findImageButton2 = QPushButton("Add to List") self.findImageCB = QCheckBox() self.findImageCB2 = QCheckBox() self.findImageCB3 = QCheckBox() self.findImageDSB = QDoubleSpinBox() self.findImageDSB.setValue(60) self.findImageForm = QFormLayout() self.findImageForm.addRow(self.findImageInfo) self.findImageForm.addRow(self.findImagePath) self.findImageForm.addRow(findImageButton) self.findImageForm.addRow("Search until find", self.findImageCB) self.findImageForm.addRow("Press after found", self.findImageCB2) self.findImageForm.addRow("Fast find (less sensivity)", self.findImageCB3) self.findImageForm.addRow(findImageButton2) self.findImageWid.setLayout(self.findImageForm) self.findImageCB.clicked.connect(self.addRowCB) findImageButton.clicked.connect(self.selectImage) findImageButton2.clicked.connect(self.findImageDo) def addRowCB(self): if self.findImageCB.isChecked(): self.findImageForm.addRow("Second wait for eact search", self.findImageDSB) else: label = self.findImageForm.labelForField(self.findImageDSB) if label is not None: label.deleteLater() self.findImageDSB.deleteLater() self.findImageDSB = QDoubleSpinBox() self.findImageDSB.setValue(60) def selectImage(self): dir_ = QFileDialog.getOpenFileName(self, 'Select a image', os.getcwd(), "Image files (*.jpg *.png)") self.findImagePath.setText(dir_[0]) def findImageDo(self): if self.findImagePath.text() == "": QMessageBox.warning(self, 'Error!', "Please choose a image.", QMessageBox.Ok) else: cb = "no" cb2 = "no" cb3 = "no" wait = 60.0 if self.findImageCB.isChecked(): cb = "yes" if self.findImageCB2.isChecked(): cb2 = "yes" if self.findImageCB3.isChecked(): cb3 = "yes" if cb == "yes": wait = str(self.findImageDSB.value()) item = [ "Find Image", "Search Until Find", cb, "Press After Found", cb2, "Fast Find", cb3, "Wait", wait, "File Path", self.findImagePath.text() ] add(item) def tab4UI(self): self.repeatTimes = QSpinBox() self.repeatTimes.setMinimum(0) self.repeatTimes.setMaximum(999999) self.repeatTimes.setValue(1) self.repeatCheckBox = QCheckBox() self.mousePositionHotkey = QLineEdit(hotkeysList[0]) self.stopActionHotkey = QLineEdit(hotkeysList[1]) self.startActionHotkey = QLineEdit(hotkeysList[2]) self.exitAppHotkey = QLineEdit(hotkeysList[3]) self.saveHotkeysPB = QPushButton("Save Hotkeys") self.facebook = QLabel( "<a href='https://www.facebook.com/fifalamoche'>Contact Me</a>") self.facebook.setAlignment(Qt.AlignRight) self.facebook.setOpenExternalLinks(True) tab4Form = QFormLayout() tab4Form.addRow(QLabel(" Repeat Settings")) tab4Form.addRow("Repeat Times :", self.repeatTimes) tab4Form.addRow("Continuous Loop :", self.repeatCheckBox) tab4Form.addRow(QLabel(" Hotkey Settings (Need Restart App)")) tab4Form.addRow("Get mouse position :", self.mousePositionHotkey) tab4Form.addRow("Stop Action :", self.stopActionHotkey) tab4Form.addRow("Start Action :", self.startActionHotkey) tab4Form.addRow("Exit App :", self.exitAppHotkey) tab4Form.addRow(self.saveHotkeysPB) tab4Form.addRow(self.facebook) self.tab4.setLayout(tab4Form)
class BashActionsDialog(QDialog): def __init__(self): super().__init__() self.mainDialog, self.wid0, self.wid1 = QWidget(), QWidget(), QWidget() self.mainDialog.setWindowModality(Qt.NonModal) self.mainLayout = QVBoxLayout(self.mainDialog) self.box0, self.box1 = QHBoxLayout(self.wid0), QHBoxLayout(self.wid1) QLabel(self.mainDialog).setPixmap( QIcon.fromTheme("applications-graphics").pixmap(64)) self.formLayout = QFormLayout() self.refreshButton = QPushButton("Refresh") self.loadButton = QPushButton("Load") self.mode = QComboBox() self.mode.addItems(("Full", "Simple")) self.widgetDocuments = QListWidget() self.widgetDocuments.setSortingEnabled(True) self.widgetDocuments.setToolTip("Choose 1 or more files") self.widgetDocuments.setSelectionMode(QAbstractItemView.MultiSelection) self.widgetDocuments.setSizeAdjustPolicy( QAbstractScrollArea.AdjustToContents) self.bashscript, self.preview = QPlainTextEdit(), QPlainTextEdit() self.bashscript.setPlaceholderText(_MSG0) self.bashscript.setToolTip(_MSG0) self.bashscript.setPlainText(Path(__file__ + ".txt").read_text()) self.preview.setPlaceholderText( "Read-Only Preview of your Bash Commands before execution.") self.preview.setToolTip( "This will run exactly as seen here, line-by-line 1 per line.") self.preview.setReadOnly(True) self.log = QPlainTextEdit() self.log.setPlaceholderText( "Read-Only Log of your Bash Commands after execution.") self.log.setToolTip("Standard output, standard error and extra info.") self.log.setReadOnly(True) self.chrt = QCheckBox("Low CPU priority") self.autoquote = QCheckBox( "Auto add quotes if the filename or path has white spaces") self.asave = QCheckBox("Auto save") self.autoquote.setChecked(True) self.asave.setChecked(True) self.mini = QCheckBox("Minimize during execution") self.qq = QCheckBox("Close after execution") self.repeats, self.delay = QSpinBox(), QSpinBox() self.backoff, self.timeout = QSpinBox(), QSpinBox() self.repeats.setRange(1, 99) self.repeats.setPrefix("Repeat ") self.repeats.setSuffix(" times") self.delay.setRange(0, 99) self.delay.setPrefix("Delay ") self.delay.setSuffix(" seconds") self.backoff.setRange(1, 9) self.backoff.setPrefix("Backoff ") self.backoff.setSuffix(" seconds") self.timeout.setRange(0, 999) self.timeout.setValue(999) self.timeout.setPrefix("Timeout at ") self.timeout.setSuffix(" seconds") self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Close | QDialogButtonBox.Help) # self.misteryButton = QPushButton("?", self.buttonBox) # self.misteryButton.setFlat(True) self.refreshButton.clicked.connect(self.loadDocuments) self.loadButton.clicked.connect(self.load_script) self.buttonBox.accepted.connect(self.confirmButton) self.buttonBox.rejected.connect(self.mainDialog.close) self.buttonBox.helpRequested.connect(lambda: open_new_tab(__url__)) self.mode.currentIndexChanged.connect(self.change_mode) self.bashscript.textChanged.connect(self.update_preview) self.kritaInstance = krita.Krita.instance() self.documentsList, self.selected = [], [] self.process = QProcess(self) # self.process.error.connect( # lambda: self.statusBar().showMessage("Info: Process Killed", 5000)) def change_mode(self, index): for item in (self.preview, self.log, self.wid0, self.wid1, self.autoquote): if index == 1: item.hide() self.formLayout.labelForField(item).hide() self.mainDialog.resize(400, 400) else: item.show() self.formLayout.labelForField(item).show() self.mainDialog.resize(800, 800) def load_script(self): self.bashscript.setPlainText(str(Path(QFileDialog.getOpenFileName( self, "Open 1 Bash Script Template", "Bash_Commands_Template.sh", "Bash Script to use as Template (*.sh);;Plain text files (*.txt)" )[0]).read_text())) def update_preview(self): script = str(self.bashscript.toPlainText()).strip() self.selected = [a.text() for a in self.widgetDocuments.selectedItems()] if not len(script): return # Nothing to do yet. elif not len(self.selected): self.preview.setPlainText(script) # We got script but no files yet. else: preview_script = script for index, selected_file in enumerate(self.selected): index, seleted_file = index + 1, str(selected_file) need_quote = self.autoquote.isChecked() and " " in seleted_file preview_script = preview_script.replace( f"FILE{index}", f'"{seleted_file}"' if need_quote else seleted_file) self.preview.setPlainText(preview_script) def initialize(self): self.loadDocuments() self.formLayout.addRow(QLabel("<center><h1>Bash Actions for Krita")) self.formLayout.addRow("Mode", self.mode) self.formLayout.addRow("Opened image files", self.widgetDocuments) self.formLayout.addRow(" ", self.refreshButton) self.formLayout.addRow("Commands template", self.bashscript) self.formLayout.addRow(" ", self.loadButton) self.formLayout.addRow("Preview", self.preview) self.formLayout.addRow("Log", self.log) self.box1.addWidget(self.repeats) self.box1.addWidget(self.delay) self.box1.addWidget(self.backoff) self.box1.addWidget(self.timeout) self.formLayout.addRow("Execution repeats", self.wid1) self.box0.addWidget(self.asave) self.box0.addWidget(self.chrt) self.box0.addWidget(self.mini) self.box0.addWidget(self.qq) self.formLayout.addRow("Execution details", self.wid0) self.formLayout.addRow("Filename correction", self.autoquote) self.mainLayout.addLayout(self.formLayout) self.mainLayout.addWidget(self.buttonBox) self.mainDialog.resize(800, 800) self.mainDialog.setWindowTitle("Bash Actions") self.mainDialog.show() self.mainDialog.activateWindow() self.bashscript.setFocus() def loadDocuments(self): self.widgetDocuments.clear() self.documentsList = [ document for document in self.kritaInstance.documents() if document.fileName()] for document in self.documentsList: self.widgetDocuments.addItem(document.fileName()) def confirmButton(self): start_time, repeat = datetime.now(), int(self.repeats.value()) end_time = int(time.time() + int(self.timeout.value())) delay, backoff = int(self.delay.value()), int(self.backoff.value()) if self.asave.isChecked(): Path(__file__ + ".txt").write_text(str(self.bashscript.toPlainText())) chrt = which("chrt") if self.chrt.isChecked() else None commands = tuple(str(self.preview.toPlainText()).strip().splitlines()) if not len(commands): return QMessageBox.warning(self, __doc__, "Nothing to execute!.") if self.mini.isChecked() and self.mainDialog.isVisible(): self.mainDialog.hide() self.log.clear() self.log.setPlainText(f"""STARTED: {start_time} by user {getuser()}. LINES OF BASH TO EXECUTE: {len(commands)}.\nTIMEOUT: {end_time} Secs. SELECTED FILES: {len(self.selected)} files.\nDELAY: {delay} Secs. BACKOFF: {backoff} Secs.\nREPEATS: {repeat} Times.\nPRIORITY: {chrt}""") while repeat: self.log.appendPlainText(f"REPETITION: {repeat} loop.") for i, cmd in enumerate(commands): cmd = f"""{chrt} -i 0 {cmd.strip()}""" if chrt else cmd.strip() self.log.appendPlainText(f"{i} EXECUTING: {cmd}.") self.process.start(cmd) self.process.waitForFinished(self.timeout.value()) self.log.appendPlainText( bytes(self.process.readAllStandardError()).decode("utf-8")) self.log.appendPlainText( bytes(self.process.readAllStandardOutput()).decode("utf-8")) sleep(delay) repeat -= 1 delay *= backoff if end_time and time.time() > end_time: self.log.appendPlainText(f"TIMEOUT: {time.time()} > {end_time}") return else: self.log.appendPlainText(f"FINISHED: {datetime.now()}.") if self.mini.isChecked() and not self.mainDialog.isVisible(): self.mainDialog.show() if self.qq.isChecked(): self.mainDialog.close() self.close()