class QFileBrowse(QWidget): def __init__(self, subfolder_name='QR Codes', *args, **kwargs): super().__init__(*args, **kwargs) self.layout = QGridLayout() self.button = QPushButton("Change save location") self.subfolder = QCheckBox("Create subfolder") self.subfolder.stateChanged.connect(self.update_display) self.button.clicked.connect(self.browse) self.subfolder_name = subfolder_name self.dialog = QFileDialog() self._base_path = pathlib.Path(".").expanduser().resolve() # output path display self.path_display = QPlainTextEdit() # make bold font = self.path_display.font() font.setWeight(QFont.Bold) self.path_display.setFont(font) # configure height self.path_display.setFixedHeight(QFontMetrics(font).height() * 2) self.path_display.setLineWrapMode(QPlainTextEdit.NoWrap) # styles self.path_display.setReadOnly(True) self.path_display.setFrameStyle(QFrame.Box | QFrame.Sunken) self.path_display.setTextInteractionFlags(Qt.TextSelectableByMouse) self.path_display.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) self.path_display.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.path_display.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # add widgets to layout self.layout.addWidget(self.button, 0, 0) self.layout.addWidget(self.subfolder, 0, 1) self.layout.addWidget(self.path_display, 1, 0, 1, 2) self.layout.setMargin(0) self.setLayout(self.layout) self.update_display() @property def save_path(self): if self.subfolder.isChecked(): return self._base_path / self.subfolder_name return self._base_path def browse(self): path = self.dialog.getExistingDirectory() if path != '': self._base_path = pathlib.Path(path).expanduser().resolve() self.update_display() def update_display(self): scrollbar = self.path_display.horizontalScrollBar() old_scroll = scrollbar.value() scrolled_to_end = old_scroll == scrollbar.maximum() self.path_display.setPlainText(str(self.save_path)) if scrolled_to_end: scrollbar.setValue(scrollbar.maximum()) else: scrollbar.setValue(old_scroll)
class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.textEdit = QPlainTextEdit() self.initUI() def initUI(self): openAction = QAction('&Open...', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open JSON file') openAction.triggered.connect(self.open) openLinkAction = QAction('&Open URL...', self) openLinkAction.setShortcut('Ctrl+L') openLinkAction.setStatusTip('Load JSON by URL') openLinkAction.triggered.connect(self.openLink) saveAction = QAction('&Save...', self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip('Save JSON file') saveAction.triggered.connect(self.save) exitAction = QAction('&Quit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) self.statusBar() menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(openAction) fileMenu.addAction(openLinkAction) fileMenu.addAction(saveAction) fileMenu.addSeparator() fileMenu.addAction(exitAction) font = self.textEdit.font() font.setFamily("monospace") font.setPointSize(14) sb = self.textEdit.verticalScrollBar() sb.setValue(sb.maximum()) self.setCentralWidget(self.textEdit) self.resize(800, 600) self.setWindowTitle("JSON Editor") self.show() def open(self): fname, _ = QFileDialog.getOpenFileName(self, 'Open JSON file', '/home') if fname == '': return f = open(fname, 'r') with f: data = f.read() self.textEdit.setPlainText(data) def openLink(self): url, ok = QInputDialog.getText(self, 'Load JSON by URL', 'Enter URL:') if not ok: return try: with request.urlopen(url) as f: data = f.read() self.textEdit.setPlainText(str(data, 'utf-8')) except (ValueError, error.URLError, error.HTTPError): msgBox = QMessageBox() msgBox.setText("Can't load JSON data") msgBox.exec_() def save(self): try: json.loads(self.textEdit.toPlainText()) except json.JSONDecodeError: msgBox = QMessageBox() msgBox.setTitle("Error") msgBox.setText("Invalid JSON") msgBox.exec_() return fname, _ = QFileDialog.getSaveFileName(self, 'Save JSON to file') f = open(fname, "w") f.write(self.textEdit.toPlainText()) f.close()