class Snippets(QDialog): def __init__(self, parent=None): super(Snippets, self).__init__(parent) # Create widgets self.setWindowModality(Qt.ApplicationModal) self.title = QLabel(self.tr("Snippet Editor")) self.saveButton = QPushButton(self.tr("Save")) self.closeButton = QPushButton(self.tr("Close")) self.clearHotkeyButton = QPushButton(self.tr("Clear Hotkey")) self.setWindowTitle(self.title.text()) self.newFolderButton = QPushButton("New Folder") self.deleteSnippetButton = QPushButton("Delete") self.newSnippetButton = QPushButton("New Snippet") self.edit = QPlainTextEdit() self.edit.setPlaceholderText("python code") self.resetting = False self.columns = 3 self.keySequenceEdit = QKeySequenceEdit(self) self.currentHotkey = QKeySequence() self.currentHotkeyLabel = QLabel("") self.currentFileLabel = QLabel() self.currentFile = "" self.snippetDescription = QLineEdit() self.snippetDescription.setPlaceholderText("optional description") #Set Editbox Size font = getMonospaceFont(self) self.edit.setFont(font) font = QFontMetrics(font) self.edit.setTabStopWidth(4 * font.width(' ')); #TODO, replace with settings API #Files self.files = QFileSystemModel() self.files.setRootPath(snippetPath) self.files.setNameFilters(["*.py"]) #Tree self.tree = QTreeView() self.tree.setModel(self.files) self.tree.setSortingEnabled(True) self.tree.hideColumn(2) self.tree.sortByColumn(0, Qt.AscendingOrder) self.tree.setRootIndex(self.files.index(snippetPath)) for x in range(self.columns): #self.tree.resizeColumnToContents(x) self.tree.header().setSectionResizeMode(x, QHeaderView.ResizeToContents) treeLayout = QVBoxLayout() treeLayout.addWidget(self.tree) treeButtons = QHBoxLayout() treeButtons.addWidget(self.newFolderButton) treeButtons.addWidget(self.newSnippetButton) treeButtons.addWidget(self.deleteSnippetButton) treeLayout.addLayout(treeButtons) treeWidget = QWidget() treeWidget.setLayout(treeLayout) # Create layout and add widgets buttons = QHBoxLayout() buttons.addWidget(self.clearHotkeyButton) buttons.addWidget(self.keySequenceEdit) buttons.addWidget(self.currentHotkeyLabel) buttons.addWidget(self.closeButton) buttons.addWidget(self.saveButton) description = QHBoxLayout() description.addWidget(QLabel(self.tr("Description: "))) description.addWidget(self.snippetDescription) vlayoutWidget = QWidget() vlayout = QVBoxLayout() vlayout.addLayout(description) vlayout.addWidget(self.edit) vlayout.addLayout(buttons) vlayoutWidget.setLayout(vlayout) hsplitter = QSplitter() hsplitter.addWidget(treeWidget) hsplitter.addWidget(vlayoutWidget) hlayout = QHBoxLayout() hlayout.addWidget(hsplitter) self.showNormal() #Fixes bug that maximized windows are "stuck" self.settings = QSettings("Vector35", "Snippet Editor") if self.settings.contains("ui/snippeteditor/geometry"): self.restoreGeometry(self.settings.value("ui/snippeteditor/geometry")) else: self.edit.setMinimumWidth(80 * font.averageCharWidth()) self.edit.setMinimumHeight(30 * font.lineSpacing()) # Set dialog layout self.setLayout(hlayout) # Add signals self.saveButton.clicked.connect(self.save) self.closeButton.clicked.connect(self.close) self.clearHotkeyButton.clicked.connect(self.clearHotkey) self.tree.selectionModel().selectionChanged.connect(self.selectFile) self.newSnippetButton.clicked.connect(self.newFileDialog) self.deleteSnippetButton.clicked.connect(self.deleteSnippet) self.newFolderButton.clicked.connect(self.newFolder) if self.settings.contains("ui/snippeteditor/selected"): selectedName = self.settings.value("ui/snippeteditor/selected") self.tree.selectionModel().select(self.files.index(selectedName), QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows) if self.tree.selectionModel().hasSelection(): self.selectFile(self.tree.selectionModel().selection(), None) self.edit.setFocus() cursor = self.edit.textCursor() cursor.setPosition(self.edit.document().characterCount()-1) self.edit.setTextCursor(cursor) else: self.readOnly(True) else: self.readOnly(True) @staticmethod def registerAllSnippets(): for action in list(filter(lambda x: x.startswith("Snippets\\"), UIAction.getAllRegisteredActions())): if action == "Snippets\\Snippet Editor...": continue UIActionHandler.globalActions().unbindAction(action) Menu.mainMenu("Tools").removeAction(action) UIAction.unregisterAction(action) for snippet in includeWalk(snippetPath, ".py"): snippetKeys = None (snippetDescription, snippetKeys, snippetCode) = loadSnippetFromFile(snippet) if not snippetDescription: actionText = "Snippets\\" + os.path.basename(snippet).rstrip(".py") else: actionText = "Snippets\\" + snippetDescription if snippetCode: if snippetKeys == None: UIAction.registerAction(actionText) else: UIAction.registerAction(actionText, snippetKeys) UIActionHandler.globalActions().bindAction(actionText, UIAction(makeSnippetFunction(snippetCode))) Menu.mainMenu("Tools").addAction(actionText, actionText) def clearSelection(self): self.keySequenceEdit.clear() self.currentHotkey = QKeySequence() self.currentHotkeyLabel.setText("") self.currentFileLabel.setText("") self.snippetDescription.setText("") self.edit.setPlainText("") self.currentFile = "" def reject(self): self.settings.setValue("ui/snippeteditor/geometry", self.saveGeometry()) if self.snippetChanged(): question = QMessageBox.question(self, self.tr("Discard"), self.tr("You have unsaved changes, quit anyway?")) if question != QMessageBox.StandardButton.Yes: return self.accept() def newFolder(self): (folderName, ok) = QInputDialog.getText(self, self.tr("Folder Name"), self.tr("Folder Name: ")) if ok and folderName: index = self.tree.selectionModel().currentIndex() selection = self.files.filePath(index) if QFileInfo(selection).isDir(): QDir(selection).mkdir(folderName) else: QDir(snippetPath).mkdir(folderName) def selectFile(self, new, old): if (self.resetting): self.resetting = False return newSelection = self.files.filePath(new.indexes()[0]) self.settings.setValue("ui/snippeteditor/selected", newSelection) if QFileInfo(newSelection).isDir(): self.readOnly(True) self.tree.clearSelection() self.currentFile = "" return if old and old.length() > 0: oldSelection = self.files.filePath(old.indexes()[0]) if not QFileInfo(oldSelection).isDir() and self.snippetChanged(): question = QMessageBox.question(self, self.tr("Discard"), self.tr("Snippet changed. Discard changes?")) if question != QMessageBox.StandardButton.Yes: self.resetting = True self.tree.selectionModel().select(old, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows) return False self.currentFile = newSelection self.loadSnippet() def loadSnippet(self): self.currentFileLabel.setText(QFileInfo(self.currentFile).baseName()) (snippetDescription, snippetKeys, snippetCode) = loadSnippetFromFile(self.currentFile) self.snippetDescription.setText(snippetDescription) if snippetDescription else self.snippetDescription.setText("") self.keySequenceEdit.setKeySequence(snippetKeys) if snippetKeys else self.keySequenceEdit.setKeySequence(QKeySequence("")) self.edit.setPlainText(snippetCode) if snippetCode else self.edit.setPlainText("") self.readOnly(False) def newFileDialog(self): (snippetName, ok) = QInputDialog.getText(self, self.tr("Snippet Name"), self.tr("Snippet Name: ")) if ok and snippetName: if not snippetName.endswith(".py"): snippetName += ".py" index = self.tree.selectionModel().currentIndex() selection = self.files.filePath(index) if QFileInfo(selection).isDir(): path = os.path.join(selection, snippetName) else: path = os.path.join(snippetPath, snippetName) self.readOnly(False) open(path, "w").close() self.tree.setCurrentIndex(self.files.index(path)) log_debug("Snippet %s created." % snippetName) def readOnly(self, flag): self.keySequenceEdit.setEnabled(not flag) self.snippetDescription.setReadOnly(flag) self.edit.setReadOnly(flag) if flag: self.snippetDescription.setDisabled(True) self.edit.setDisabled(True) else: self.snippetDescription.setEnabled(True) self.edit.setEnabled(True) def deleteSnippet(self): selection = self.tree.selectedIndexes()[::self.columns][0] #treeview returns each selected element in the row snippetName = self.files.fileName(selection) question = QMessageBox.question(self, self.tr("Confirm"), self.tr("Confirm deletion: ") + snippetName) if (question == QMessageBox.StandardButton.Yes): log_debug("Deleting snippet %s." % snippetName) self.clearSelection() self.files.remove(selection) self.registerAllSnippets() def snippetChanged(self): if (self.currentFile == "" or QFileInfo(self.currentFile).isDir()): return False (snippetDescription, snippetKeys, snippetCode) = loadSnippetFromFile(self.currentFile) if snippetKeys == None and not self.keySequenceEdit.keySequence().isEmpty(): return True if snippetKeys != None and snippetKeys != self.keySequenceEdit.keySequence().toString(): return True return self.edit.toPlainText() != snippetCode or \ self.snippetDescription.text() != snippetDescription def save(self): log_debug("Saving snippet %s" % self.currentFile) outputSnippet = open(self.currentFile, "w") outputSnippet.write("#" + self.snippetDescription.text() + "\n") outputSnippet.write("#" + self.keySequenceEdit.keySequence().toString() + "\n") outputSnippet.write(self.edit.toPlainText()) outputSnippet.close() self.registerAllSnippets() def clearHotkey(self): self.keySequenceEdit.clear()
class micGui(QWidget): app_icon = QIcon() app = QApplication([]) handlers = han.Handlers(50) changesAvailable = True changed = -1 #0: handle, #1: type, #2: resolution, #3: rate handleUpdated = -1 sliders = [] comboBoxResol = 0 comboBoxRate = 0 resolIndex = -1 rateIndex = -1 modeIndex = -1 filterIndex = -1 guiSettings = guiSettings(initValues=[0, 2, 3, 0, 50]) queue = Queue() # Initializes graphical setup and updates queue def __init__(self, queue, numberOfHandles=10): super(micGui, self).__init__() self.setupGui(numberOfHandles) self.queue = queue # Configs graphical elements and their initializations def setupGui(self, numberOfHandles): self.configWindow() self.configureBackground() self.resolutionOptions() self.samplingRateOptions() self.modeOptions() self.showSettingsButton() for i in range(numberOfHandles): self.sliders.append( self.createImgSlider("./mic/gui/filter-gui/slider.png", i)) self.sliders[i].valueChanged[int].connect( lambda val, index=i: self.setHandlers(val, index)) self.handlers.register_callback(self.updateHandlersStatus) # Updates handle value when signal is received and sends # a signal for filter updater def updateHandlersStatus(self, handleNumber): self.changesAvailable = True self.handleUpdated = handleNumber self.changed = 0 # Sends gui settings def setHandlers(self, newVal, handlerID): self.guiSettings.updatesAvailable = True self.guiSettings.handleSelected = handlerID self.guiSettings.handleValue = newVal self.queue.put(self.guiSettings) # Initializes resolution options and it's changes callback def resolutionOptions(self): resolutions = ["Ultra High", "High", "Normal", "Low", "Ultra Low"] self.comboBoxResol = self.setComboBox(2, 542, 187, "comboBoxResol", resolutions) l = lambda optionSelected, optionIndex=2: self.updateComboBoxStatus( optionSelected, optionIndex) self.comboBoxResol.currentIndexChanged[int].connect(l) # Initializes sampling rate options and it's changes callback def samplingRateOptions(self): rates = ["48000", "44100", "32000", "22050", "11025", "8000"] self.comboBoxRate = self.setComboBox(3, 542, 125, "comboBoxRate", rates) l = lambda optionSelected, optionIndex=3: self.updateComboBoxStatus( optionSelected, optionIndex) self.comboBoxRate.currentIndexChanged[int].connect(l) # Initializes mode options and it's changes callback def modeOptions(self): modes = ["FIR (slow)", "Butterworth (fast)", "Devil", "Goblin"] self.comboBoxMode = self.setComboBox(0, 542, 63, "comboBoxMode", modes) l = lambda optionSelected, optionIndex=1: self.updateComboBoxStatus( optionSelected, optionIndex) self.comboBoxMode.currentIndexChanged[int].connect(l) # If any combo box option is changed, this callback is called. # Sends update to updates queue. @QtCore.Slot(int) def updateComboBoxStatus(self, newVal, changeCode): self.changesAvailable = True self.changed = changeCode if (changeCode == 3): self.rateIndex = newVal self.guiSettings.rateSelected = newVal elif (changeCode == 2): self.resolIndex = newVal self.guiSettings.resolutionSelected = newVal elif (changeCode == 1): self.filterIndex = newVal self.guiSettings.filterSelected = newVal self.queue.put(self.guiSettings) # Sets background image def configureBackground(self): image = "mic/gui/filter-gui/UI.png" self.text_field = QPlainTextEdit(self) self.text_field.setDisabled(True) self.text_field.setMinimumSize(720, 301) self.text_field.setStyleSheet("background-image: url(" + image + "); background-attachment: fixed") # Initializes combo box def setComboBox(self, startingIndex=0, xPos=0, yPos=0, objName="default", items=[]): combo = QComboBox(self) for item in items: combo.addItem(item) combo.setObjectName(objName) combo.setGeometry(QRect(xPos, yPos, 125, 22)) combo.setCurrentIndex(startingIndex) combo.setStyleSheet( "background-color: rgb(47, 47, 47) ; color: rgb(255, 96, 96);") return combo # Initializes Windows and title bar icons def configIcons(self): self.app_icon.addFile('mic/gui/filter-gui/icon/icon16.png', QSize(16, 16)) self.app_icon.addFile('mic/gui/filter-gui/icon/icon24.png', QSize(24, 24)) self.app_icon.addFile('mic/gui/filter-gui/icon/icon32.png', QSize(32, 32)) self.app_icon.addFile('mic/gui/filter-gui/icon/icon48.png', QSize(48, 48)) self.app_icon.addFile('mic/gui/filter-gui/icon/icon256.png', QSize(256, 256)) self.app.setWindowIcon(self.app_icon) # Initializes general window's elements like # title Bar and window size def configWindow(self): self.configIcons() self.setWindowTitle('Bokus Multiband Filter') self.setWindowFlags(self.windowFlags() | QtCore.Qt.CustomizeWindowHint) self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowMaximizeButtonHint) self.setFixedSize(720, 301) # Creates an slider, with an image as a handle def createImgSlider(self, imgPath, index): xPosition = 36 + 47 * index slider = QSlider(self) slider.setObjectName(u"slider" + str(index)) slider.setGeometry(QRect(xPosition, -1, 51, 300)) slider.setCursor(QCursor(Qt.OpenHandCursor)) slider.setMouseTracking(False) slider.setFocusPolicy(Qt.StrongFocus) slider.setAcceptDrops(False) slider.setAutoFillBackground(False) slider.setStyleSheet(u"QSlider::handle:vertical {\n" " image: url(" + imgPath + ");\n" " width: 90px;\n" " height: 90px\n" "}\n" "\n" "QSlider::groove:vertical{\n" " background: rgba(0, 0, 0, 0);\n" "}") slider.setValue(50) slider.setSliderPosition(50) slider.setOrientation(Qt.Vertical) slider.setInvertedAppearance(False) return slider # [DEPRECATED] loads GUI from from.ui (PyQt) def load_ui(self): loader = QUiLoader() path = os.path.join(os.path.dirname(__file__), "./gui/filter-gui/form2.ui") ui_file = QFile(path) ui_file.open(QFile.ReadOnly) loader.load(ui_file, self) ui_file.close() # [DEPRECATED. Replaced with combo boxes] loads buttons for mode selecting. def filterModeButtons(self): self.filterTypeButtons = QButtonGroup(self) self.configFilterTypeButtons("firButton", True, 560, 49, 0) self.configFilterTypeButtons("iirButton", False, 560, 68, 1) self.configFilterTypeButtons("devilButton", False, 560, 86, 2) self.configFilterTypeButtons("goblinButton", False, 560, 104, 3) # [DEPRECATED. Used in filterModeButtons] def configFilterTypeButtons(self, name=u"default", checked=False, xPos=0, yPos=0, idButton=0): button = QRadioButton(self) button.setObjectName(name) button.setEnabled(True) button.setGeometry(QRect(xPos, yPos, 82, 17)) button.setCursor(QCursor(Qt.PointingHandCursor)) button.setChecked(checked) lam = lambda id=idButton: self.buttonChecked(id) self.connect(button, SIGNAL("clicked()"), lam) self.filterTypeButtons.addButton(button, idButton) # [DEPRECATED. Used in filterModeButtons] def buttonChecked(self, idButton): self.filterIndex = idButton self.guiSettings.filterSelected = idButton self.queue.put(self.guiSettings) # Properly closes GUI if flag is received def sys_exit(self, exitProgram): self.app.exec_() exitProgram.value = True self.queue.put(None) sys.exit() # Properly closes settings window def closeEvent(self, event): self.closeSettings() # Properly closes settings window def closeSettings(self): if hasattr(self, 'sets'): self.sets.close() # Initializes button for opening settings def showSettingsButton(self): image = "./mic/gui/filter-gui/settings-button.png" imageHover = "./mic/gui/filter-gui/settings-button-hover.png" button = QPushButton("", self) button.setGeometry(685, 10, 24, 27) button.setStyleSheet("border-radius : 50") button.setStyleSheet("QPushButton {border-image: url(" + image + "); } QPushButton:hover { border-image: url(" + imageHover + ")}") button.clicked.connect(self.openSettings) self.settingsButton = button # Shows settings def openSettings(self): self.sets = settingsWindow() self.sets.show()