def setup_menu(self): menubar = QMenuBar(self) menubar.setGeometry(QRect(0, 0, 868, 21)) menu_file = QMenu(menubar) menu_file.setTitle('File') menubar.addAction(menu_file.menuAction()) action_import = QAction(self) action_import.setText('Import...') menu_file.addAction(action_import) action_export = QAction(self) action_export.setText('Export...') menu_file.addAction(action_export) action_exit = QAction(self) action_exit.setText('Exit') menu_file.addAction(action_exit) menu_view = QMenu(menubar) menu_view.setTitle('View') menubar.addAction(menu_view.menuAction()) action_toggle_log = QAction(self) action_toggle_log.setText('Debug Log') menu_view.addAction(action_toggle_log) action_import.triggered.connect(self.import_data) action_exit.triggered.connect(self.close) action_toggle_log.triggered.connect(self.toggle_log) action_export.triggered.connect(self.export_data) self.setMenuBar(menubar)
class Window(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setFixedSize(800, 685) self.setWindowTitle("Spotify Lyrics Finder") icon = QIcon("logo.ico") self.setWindowIcon(icon) self.CenterPanel = UiPanel(self) self.setCentralWidget(self.CenterPanel) self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 800, 21)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle("File") self.setMenuBar(self.menubar) self.statusbar = QStatusBar(self) self.statusbar.setSizeGripEnabled(False) self.setStatusBar(self.statusbar) self.actionClose = QAction(self) self.actionClose.setText("Close") self.actionClose.setShortcut("Ctrl+Q") self.actionProject = QAction(self) self.actionProject.setText("Copyright © White Aspect") self.menuFile.addAction(self.actionClose) self.menubar.addAction(self.menuFile.menuAction()) self.actionClose.triggered.connect(close_app) self.actionProject.triggered.connect(project_website)
def CreateHelpEntryForMenubar(parent:QtWidgets.QMenuBar): if issubclass(type(parent), QtWidgets.QMenuBar) is True: menuEdit = QtWidgets.QMenu(parent) menuEdit.setObjectName("menuHelp") menuEdit.setTitle("Help") parent.addAction(menuEdit.menuAction()) return menuEdit else: return None
class EpoxUi(QMainWindow): """GUI for EpoxyApp""" def __init__(self): """Initiates an instance of EpoxUi - GUI for 'Epoxy Calculator' app""" super().__init__() # Set main window's properties self.setWindowTitle('Mix Calculator') # Set the central widget self.generalMainLayout = QVBoxLayout() # main layout instance self.centralWidget = QWidget() # main widget instance self.centralWidget.setLayout(self.generalMainLayout) self.setCentralWidget(self.centralWidget) # Set top menu bar self.menubar = QMenuBar(self) self.menuData = QMenu(self.menubar) self.setMenuBar(self.menubar) # Create actions self.actionReadData = QAction(self) self.actionWriteData = QAction(self) self.menuData.addAction(self.actionReadData) self.menuData.addAction(self.actionWriteData) self.menubar.addAction(self.menuData.menuAction()) # Lable top menu self.labelTopMenuBar() # Creating particular parts of the GUI self.dropDownRegion = DropDownMenu() self.inputRegion = InputBoxes() # Attaching layouts to mainWindoLayout self.inputRegion.attachInputBoxes(self.generalMainLayout) self.dropDownRegion.attachDropDownMenu(self.generalMainLayout) def getDropDownMenu(self): """Returns the DropDownMenu class""" return self.dropDownRegion def getInputBoxes(self): """Returns the InputBoxes class""" return self.inputRegion def getReadWriteActions(self): """Return read and write QActions.""" return (self.actionReadData, self.actionWriteData) def labelTopMenuBar(self): """Set visible labels for top menu bar.""" self.menuData.setTitle("&Source file") self.actionReadData.setText("Read") self.actionWriteData.setText("Write")
def initUI(self): mainMenu = self.menuBar() menu = QMenuBar() exitButton = QAction(QIcon('images/exit.png'), 'Exit', self) exitButton.setShortcut('Ctrl+Q') exitButton.setStatusTip('Exit application') exitButton.triggered.connect(self.close_app) menu.addAction(exitButton) mainMenu.setCornerWidget(menu) self.showFullScreen()
class WinForm(QMainWindow): def __init__(self, parent=None): super(WinForm, self).__init__(parent) self.setWindowTitle("Widget Test") self.resize(400, 300) screen = QDesktopWidget().size() size = self.size() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) self.menubar = QMenuBar(self) self.menu = QMenu('File') self.menubar.addAction(self.menu.menuAction()) self.setMenuBar(self.menubar)
def _setup_(self): menu_bar = QMenuBar() file_menu = menu_bar.addMenu('File') open_action = file_menu.addAction('Open') open_action.triggered.connect(self.data_context.open) save_action = file_menu.addAction('Save') save_action.triggered.connect(self.data_context.save) save_as_action = file_menu.addAction('Save As') save_as_action.triggered.connect(self.data_context.save_as) load_from_matplot_action = menu_bar.addAction('Import from Matplotlib') load_from_matplot_action.triggered.connect(self._import_matplotlib_colormap_) self._layout.addWidget(menu_bar, 0, 0, 1, 2, Qt.AlignLeft) self._plot = PlotMasterWidget() self.bindings.set_binding('title', self._plot, 'set_title') self._red_plot = self._plot.plot(0, 0, 'r', name='red', allow_remove=False) self._green_plot = self._plot.plot(0, 0, 'g', name='green', allow_remove=False) self._blue_plot = self._plot.plot(0, 0, 'b', name='blue', allow_remove=False) self._plot.set_xlabel('value') self._plot.set_ylabel('color value') self._layout.addWidget(self._plot, 1, 1) tool_box = QGroupBox('Tools') tool_box_layout = QGridLayout() tool_box_layout.setAlignment(Qt.AlignLeft | Qt.AlignTop) tool_box.setLayout(tool_box_layout) self._layout.addWidget(tool_box, 1, 0) self._add_range_slider_('colors', tool_box_layout, 0) self._add_range_slider_('red', tool_box_layout, 1) self._add_range_slider_('green', tool_box_layout, 2) self._add_range_slider_('blue', tool_box_layout, 3) image_display = self.add_widget(ImageRenderWidget(keep_aspect_ratio=False), 'color_image', 'set_image', height=50) self._layout.addWidget(image_display, 2, 0, 1, 2, Qt.AlignJustify)
class Example(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): #self._layout = QHBoxLayout(self) self._widget = QWidget(self) #self._layout.addWidget(self._widget) self._menuBar = QMenuBar(self._widget) exitAct = QAction(QIcon('exit.png'), '&Exit', self) exitAct.setShortcut('Ctrl+Q') exitAct.setStatusTip('Exit application') exitAct.triggered.connect(qApp.quit) self.statusBar() #menubar = self.menuBar() menubar = self._menuBar fileMenu = menubar.addMenu('&File') fileMenu.addAction(exitAct) act = self._menuBar.addAction('test') act.setShortcut(QKeySequence('Ctrl+M')) def testCb(): print('hello') act.triggered.connect(testCb) act.setShortcutContext(Qt.WidgetShortcut) print('_menuBar parent', self._menuBar.parent()) print('act parent', act.parent()) print('_widget parent', self._widget.parent()) #act.setParent(self) #print(act.parent()) self.addAction(act) # This is important for Qt.WidgetShortcut # the Example is focused, and it's menu's act can trigger # Qt.WidgetShortcut context action #self.setFocus() #act.parent().setFocus() print('focusWidget', QApplication.focusWidget()) def cb(): tt = QApplication.focusWidget() print(tt) from PyQt5.Qt import QShortcut self.short0 = QShortcut(QKeySequence('Ctrl+N'), self) self.short0.activated.connect(cb) self.setGeometry(300, 300, 300, 200) self.setWindowTitle('Simple menu') self.show()
def _setup_menu_bar(self): menu_bar = QMenuBar(self) menu_bar.setObjectName(u"menuBar") menu_bar.setGeometry(QRect(0, 0, 800, 20)) menu_analysis_selection = QMenu(menu_bar) menu_analysis_selection.setObjectName(u"menu_analysis_selection") menu_bar.addAction(menu_analysis_selection.menuAction()) menu_analysis_selection.setTitle("Analysis Selection") action_dyssynchrony_analysis = QAction(self) action_dyssynchrony_analysis.setObjectName( u"action_dyssynchrony_analysis") menu_analysis_selection.addAction(action_dyssynchrony_analysis) action_dyssynchrony_analysis.triggered.connect( lambda _: self._go_to_image_selection()) action_dyssynchrony_analysis.setText(u"Dyssynchrony Analysis") self.setMenuBar(menu_bar)
def Admin(self): self.checked = [] dirs = [''] + os.listdir('Data') dirs.remove('Origin') action_close = QAction('닫기') action_close.triggered.connect(self.CloseProject) action_delete = QAction('삭제') action_delete.setShortcut('Alt+2') action_delete.triggered.connect(self.DeleteProject) menubar = QMenuBar() menubar.addAction(action_close) menubar.addAction(action_delete) self.table = QTableWidget() self.table.setRowCount(0) self.table.setColumnCount(len(['선택', '프로젝트명'])) self.table.setHorizontalHeaderLabels(['선택', '프로젝트명']) style = "QTableWidget{color: black;}" self.table.setStyleSheet(style) for row, project in enumerate(dirs): self.table.insertRow(row) self.table.setRowHeight(row, 50) self.__checkbox__(self.table, row, 0) item = QTableWidgetItem(project) item.setFlags(Qt.ItemIsEditable) self.table.setItem(row, 1, item) self.table.resizeColumnsToContents() self.table.hideRow(0) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setStretchLastSection(True) layout = QVBoxLayout() layout.addWidget(menubar) layout.addWidget(self.table) self.dig_project = QDialog(self) self.dig_project.setLayout(layout) self.dig_project.setWindowTitle('프로젝트 관리') self.dig_project.setFixedWidth(400) self.dig_project.setFixedHeight(800) self.dig_project.exec_()
def __init__(self, args): super(MainWindow, self).__init__() self.setFixedSize( QSize(args.main_window_width, args.main_window_height)) self.main_board = MainBoard(args.image_size, args.device, args.pretrained_model, args.n_res) main_menubar = QMenuBar() main_menubar.addAction('Upload', self.uploadImage) main_menubar.addAction('Save', self.saveImage) main_menubar.addAction('Origin', self.getOriginImage) main_menubar.addAction('Translate', self.getTranslateImage) self.setMenuBar(main_menubar) self.setCentralWidget(self.main_board)
def __init__(self): # Constructor de clase para la interfaz grafica super().__init__() caja_v = QVBoxLayout() caja_regex = QHBoxLayout() menu_bar = QMenuBar() menu_bar.addAction("About", self.about) self.txt_regex = QLineEdit() self.txt_a_tratar = QPlainTextEdit() self.txt_coincidencias = QPlainTextEdit() btn_probar = QPushButton("Probar") caja_regex.addWidget(QLabel("Expresión:")) caja_regex.addWidget(self.txt_regex) caja_regex.addWidget(btn_probar) self.chk_case = QCheckBox("Mayúsculas") caja_opciones = QHBoxLayout() caja_opciones.addWidget(QLabel("Texto a tratar:")) caja_opciones.addStretch(1) caja_opciones.addWidget(self.chk_case) caja_v.setMenuBar(menu_bar) caja_v.addLayout(caja_regex) caja_v.addLayout(caja_opciones) caja_v.addWidget(self.txt_a_tratar) caja_v.addWidget(QLabel("Coincidencias:")) caja_v.addWidget(self.txt_coincidencias) btn_probar.pressed.connect(self.evaluar) self.txt_regex.pyqtConfigure(clearButtonEnabled=True) self.txt_regex.pyqtConfigure(placeholderText="Inserte su regex") self.txt_regex.textEdited.connect(self.reset) self.txt_a_tratar.pyqtConfigure(placeholderText="Insete su texto a tratar") self.txt_coincidencias.setReadOnly(True) self.setLayout(caja_v) self.setWindowTitle("Evaluador de RegEx") self.setWindowIcon(QIcon("zorro.png")) self.resize(400, 350) self.centrar() self.show()
class DirectoriesDialog(QMainWindow): def __init__(self, app, **kwargs): super().__init__(None, **kwargs) self.app = app self.lastAddedFolder = platform.INITIAL_FOLDER_IN_DIALOGS self.recentFolders = Recent(self.app, "recentFolders") self._setupUi() self.directoriesModel = DirectoriesModel(self.app.model.directory_tree, view=self.treeView) self.directoriesDelegate = DirectoriesDelegate() self.treeView.setItemDelegate(self.directoriesDelegate) self._setupColumns() self.app.recentResults.addMenu(self.menuLoadRecent) self.app.recentResults.addMenu(self.menuRecentResults) self.recentFolders.addMenu(self.menuRecentFolders) self._updateAddButton() self._updateRemoveButton() self._updateLoadResultsButton() self._setupBindings() def _setupBindings(self): self.scanButton.clicked.connect(self.scanButtonClicked) self.loadResultsButton.clicked.connect(self.actionLoadResults.trigger) self.addFolderButton.clicked.connect(self.actionAddFolder.trigger) self.removeFolderButton.clicked.connect(self.removeFolderButtonClicked) self.treeView.selectionModel().selectionChanged.connect(self.selectionChanged) self.app.recentResults.itemsChanged.connect(self._updateLoadResultsButton) self.recentFolders.itemsChanged.connect(self._updateAddButton) self.recentFolders.mustOpenItem.connect(self.app.model.add_directory) self.directoriesModel.foldersAdded.connect(self.directoriesModelAddedFolders) self.app.willSavePrefs.connect(self.appWillSavePrefs) def _setupActions(self): # (name, shortcut, icon, desc, func) ACTIONS = [ ("actionLoadResults", "Ctrl+L", "", tr("Load Results..."), self.loadResultsTriggered), ("actionShowResultsWindow", "", "", tr("Results Window"), self.app.showResultsWindow), ("actionAddFolder", "", "", tr("Add Folder..."), self.addFolderTriggered), ] createActions(ACTIONS, self) def _setupMenu(self): self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 42, 22)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle(tr("File")) self.menuView = QMenu(self.menubar) self.menuView.setTitle(tr("View")) self.menuHelp = QMenu(self.menubar) self.menuHelp.setTitle(tr("Help")) self.menuLoadRecent = QMenu(self.menuFile) self.menuLoadRecent.setTitle(tr("Load Recent Results")) self.setMenuBar(self.menubar) self.menuFile.addAction(self.actionLoadResults) self.menuFile.addAction(self.menuLoadRecent.menuAction()) self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionQuit) self.menuView.addAction(self.app.actionPreferences) self.menuView.addAction(self.actionShowResultsWindow) self.menuView.addAction(self.app.actionIgnoreList) self.menuHelp.addAction(self.app.actionShowHelp) self.menuHelp.addAction(self.app.actionOpenDebugLog) self.menuHelp.addAction(self.app.actionAbout) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) # Recent folders menu self.menuRecentFolders = QMenu() self.menuRecentFolders.addAction(self.actionAddFolder) self.menuRecentFolders.addSeparator() # Recent results menu self.menuRecentResults = QMenu() self.menuRecentResults.addAction(self.actionLoadResults) self.menuRecentResults.addSeparator() def _setupUi(self): self.setWindowTitle(self.app.NAME) self.resize(420, 338) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) self.promptLabel = QLabel(tr('Select folders to scan and press "Scan".'), self.centralwidget) self.verticalLayout.addWidget(self.promptLabel) self.treeView = QTreeView(self.centralwidget) self.treeView.setSelectionMode(QAbstractItemView.ExtendedSelection) self.treeView.setSelectionBehavior(QAbstractItemView.SelectRows) self.treeView.setAcceptDrops(True) triggers = ( QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed | QAbstractItemView.SelectedClicked ) self.treeView.setEditTriggers(triggers) self.treeView.setDragDropOverwriteMode(True) self.treeView.setDragDropMode(QAbstractItemView.DropOnly) self.treeView.setUniformRowHeights(True) self.verticalLayout.addWidget(self.treeView) self.horizontalLayout = QHBoxLayout() self.removeFolderButton = QPushButton(self.centralwidget) self.removeFolderButton.setIcon(QIcon(QPixmap(":/minus"))) self.removeFolderButton.setShortcut("Del") self.horizontalLayout.addWidget(self.removeFolderButton) self.addFolderButton = QPushButton(self.centralwidget) self.addFolderButton.setIcon(QIcon(QPixmap(":/plus"))) self.horizontalLayout.addWidget(self.addFolderButton) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.loadResultsButton = QPushButton(self.centralwidget) self.loadResultsButton.setText(tr("Load Results")) self.horizontalLayout.addWidget(self.loadResultsButton) self.scanButton = QPushButton(self.centralwidget) self.scanButton.setText(tr("Scan")) self.scanButton.setDefault(True) self.horizontalLayout.addWidget(self.scanButton) self.verticalLayout.addLayout(self.horizontalLayout) self.setCentralWidget(self.centralwidget) self._setupActions() self._setupMenu() if self.app.prefs.directoriesWindowRect is not None: self.setGeometry(self.app.prefs.directoriesWindowRect) else: moveToScreenCenter(self) def _setupColumns(self): header = self.treeView.header() header.setStretchLastSection(False) header.setSectionResizeMode(0, QHeaderView.Stretch) header.setSectionResizeMode(1, QHeaderView.Fixed) header.resizeSection(1, 100) def _updateAddButton(self): if self.recentFolders.isEmpty(): self.addFolderButton.setMenu(None) else: self.addFolderButton.setMenu(self.menuRecentFolders) def _updateRemoveButton(self): indexes = self.treeView.selectedIndexes() if not indexes: self.removeFolderButton.setEnabled(False) return self.removeFolderButton.setEnabled(True) def _updateLoadResultsButton(self): if self.app.recentResults.isEmpty(): self.loadResultsButton.setMenu(None) else: self.loadResultsButton.setMenu(self.menuRecentResults) # --- QWidget overrides def closeEvent(self, event): event.accept() if self.app.model.results.is_modified: title = tr("Unsaved results") msg = tr("You have unsaved results, do you really want to quit?") if not self.app.confirm(title, msg): event.ignore() if event.isAccepted(): QApplication.quit() # --- Events def addFolderTriggered(self): title = tr("Select a folder to add to the scanning list") flags = QFileDialog.ShowDirsOnly dirpath = str(QFileDialog.getExistingDirectory(self, title, self.lastAddedFolder, flags)) if not dirpath: return self.lastAddedFolder = dirpath self.app.model.add_directory(dirpath) self.recentFolders.insertItem(dirpath) def appWillSavePrefs(self): self.app.prefs.directoriesWindowRect = self.geometry() def directoriesModelAddedFolders(self, folders): for folder in folders: self.recentFolders.insertItem(folder) def loadResultsTriggered(self): title = tr("Select a results file to load") files = ";;".join([tr("dupeGuru Results (*.dupeguru)"), tr("All Files (*.*)")]) destination = QFileDialog.getOpenFileName(self, title, "", files) if destination: self.app.model.load_from(destination) self.app.recentResults.insertItem(destination) def removeFolderButtonClicked(self): self.directoriesModel.model.remove_selected() def scanButtonClicked(self): if self.app.model.results.is_modified: title = tr("Start a new scan") msg = tr("You have unsaved results, do you really want to continue?") if not self.app.confirm(title, msg): return self.app.model.start_scanning() def selectionChanged(self, selected, deselected): self._updateRemoveButton()
class Ui_MainWindow(QMainWindow): def __init__(self): super(Ui_MainWindow, self).__init__() self.setWindowIcon(QIcon('icon.ico')) self.setFixedSize(481, 447) def setupUi(self): self.centralwidget = QWidget(self) self.verticalLayoutWidget = QWidget(self.centralwidget) self.verticalLayoutWidget.setGeometry(QRect(20, 50, 121, 271)) self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.checkBox = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox) self.checkBox_2 = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox_2) self.checkBox_4 = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox_4) self.checkBox_3 = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox_3) self.checkBox_8 = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox_8) self.checkBox_5 = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox_5) self.checkBox_7 = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox_7) self.checkBox_6 = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox_6) self.checkBox_9 = QCheckBox(self.verticalLayoutWidget) self.verticalLayout.addWidget(self.checkBox_9) self.verticalLayoutWidget_2 = QWidget(self.centralwidget) self.verticalLayoutWidget_2.setGeometry(QRect(170, 50, 131, 271)) self.verticalLayout_2 = QVBoxLayout(self.verticalLayoutWidget_2) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.checkBox_10 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_10) self.checkBox_11 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_11) self.checkBox_12 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_12) self.checkBox_13 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_13) self.checkBox_14 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_14) self.checkBox_15 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_15) self.checkBox_16 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_16) self.checkBox_17 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_17) self.checkBox_18 = QCheckBox(self.verticalLayoutWidget_2) self.verticalLayout_2.addWidget(self.checkBox_18) self.verticalLayoutWidget_3 = QWidget(self.centralwidget) self.verticalLayoutWidget_3.setGeometry(QRect(330, 50, 131, 271)) self.verticalLayout_3 = QVBoxLayout(self.verticalLayoutWidget_3) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.checkBox_19 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_19) self.checkBox_20 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_20) self.checkBox_21 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_21) self.checkBox_22 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_22) self.checkBox_23 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_23) self.checkBox_24 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_24) self.checkBox_25 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_25) self.checkBox_26 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_26) self.checkBox_27 = QCheckBox(self.verticalLayoutWidget_3) self.verticalLayout_3.addWidget(self.checkBox_27) self.label_note = QLabel(self.centralwidget) self.label_note.setGeometry(QRect(20, 340, 350, 16)) self.horizontalLayoutWidget = QWidget(self.centralwidget) self.horizontalLayoutWidget.setGeometry(QRect(379, 380, 81, 31)) self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) self.button_uninstall = QPushButton(self.horizontalLayoutWidget) self.horizontalLayout.addWidget(self.button_uninstall) self.label_info = QLabel(self.centralwidget) self.label_info.setGeometry(QRect(20, 20, 331, 20)) self.progressbar = QProgressBar(self.centralwidget) self.progressbar.setGeometry(QRect(20, 40, 175, 10)) self.progressbar.hide() self.horizontalLayoutWidget_2 = QWidget(self.centralwidget) self.horizontalLayoutWidget_2.setGeometry(QRect(20, 380, 160, 31)) self.horizontalLayout_2 = QHBoxLayout(self.horizontalLayoutWidget_2) self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) self.button_select_all = QPushButton(self.horizontalLayoutWidget_2) self.horizontalLayout_2.addWidget(self.button_select_all) self.button_deselect_all = QPushButton(self.horizontalLayoutWidget_2) self.horizontalLayout_2.addWidget(self.button_deselect_all) self.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 481, 21)) self.menuHelp = QMenu(self.menubar) self.setMenuBar(self.menubar) self.actionRefresh = QAction(self) self.actionHomepage = QAction(self) self.actionAbout = QAction(self) self.actionQuit = QAction(self) self.menuHelp.addAction(self.actionRefresh) self.menuHelp.addAction(self.actionHomepage) self.menuHelp.addAction(self.actionAbout) self.menuHelp.addSeparator() self.menuHelp.addAction(self.actionQuit) self.menubar.addAction(self.menuHelp.menuAction()) self.retranslateUi() QMetaObject.connectSlotsByName(self) def retranslateUi(self): _translate = QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "PyDebloatX")) self.menuHelp.setTitle(_translate("MainWindow", "&Help")) self.actionRefresh.setText(_translate("MainWindow", "&Refresh")) self.actionRefresh.setShortcut(_translate("MainWindow", "Ctrl+R")) self.actionHomepage.setText(_translate("MainWindow", "&Github")) self.actionHomepage.setShortcut(_translate("MainWindow", "Ctrl+G")) self.actionAbout.setText(_translate("MainWindow", "&About")) self.actionAbout.setShortcut(_translate("MainWindow", "Ctrl+A")) self.actionQuit.setText(_translate("MainWindow", "&Quit")) self.actionQuit.setShortcut(_translate("MainWindow", "Ctrl+Q")) self.label_info.setText( _translate("MainWindow", "Updating list of installed apps...")) self.checkBox.setText(_translate("MainWindow", "3D Viewer")) self.checkBox_2.setText(_translate("MainWindow", "Alarms and Clock")) self.checkBox_3.setText(_translate("MainWindow", "Calculator")) self.checkBox_4.setText(_translate("MainWindow", "Calendar and Mail")) self.checkBox_5.setText(_translate("MainWindow", "Camera")) self.checkBox_6.setText(_translate("MainWindow", "Get Help")) self.checkBox_7.setText(_translate("MainWindow", "Get Started")) self.checkBox_8.setText(_translate("MainWindow", "Groove Music")) self.checkBox_9.setText(_translate("MainWindow", "Maps")) self.checkBox_10.setText(_translate("MainWindow", "Messaging")) self.checkBox_11.setText(_translate("MainWindow", "Money")) self.checkBox_12.setText(_translate("MainWindow", "Movies && TV")) self.checkBox_13.setText(_translate("MainWindow", "News")) self.checkBox_14.setText(_translate("MainWindow", "Office")) self.checkBox_15.setText(_translate("MainWindow", "OneNote")) self.checkBox_16.setText(_translate("MainWindow", "Paint 3D")) self.checkBox_17.setText(_translate("MainWindow", "People")) self.checkBox_18.setText(_translate("MainWindow", "Photos")) self.checkBox_19.setText(_translate("MainWindow", "Skype")) self.checkBox_20.setText(_translate("MainWindow", "Solitaire")) self.checkBox_21.setText(_translate("MainWindow", "Sports")) self.checkBox_22.setText(_translate("MainWindow", "Store")) self.checkBox_23.setText(_translate("MainWindow", "Voice Recorder")) self.checkBox_24.setText(_translate("MainWindow", "Weather")) self.checkBox_25.setText(_translate("MainWindow", "Windows Feedback")) self.checkBox_26.setText(_translate("MainWindow", "Xbox")) self.checkBox_27.setText(_translate("MainWindow", "Your Phone")) self.label_note.setText( _translate( "MainWindow", "NOTE: Microsoft Edge and Cortana cannot be uninstalled using this GUI." )) self.button_select_all.setText(_translate("MainWindow", "Select All")) self.button_deselect_all.setText( _translate("MainWindow", "Deselect All")) self.button_uninstall.setText(_translate("MainWindow", "Uninstall"))
class DirectoriesDialog(QMainWindow): def __init__(self, app, **kwargs): super().__init__(None, **kwargs) self.app = app self.lastAddedFolder = platform.INITIAL_FOLDER_IN_DIALOGS self.recentFolders = Recent(self.app, 'recentFolders') self._setupUi() self.directoriesModel = DirectoriesModel(self.app.model.directory_tree, view=self.treeView) self.directoriesDelegate = DirectoriesDelegate() self.treeView.setItemDelegate(self.directoriesDelegate) self._setupColumns() self.app.recentResults.addMenu(self.menuLoadRecent) self.app.recentResults.addMenu(self.menuRecentResults) self.recentFolders.addMenu(self.menuRecentFolders) self._updateAddButton() self._updateRemoveButton() self._updateLoadResultsButton() self._setupBindings() def _setupBindings(self): self.scanButton.clicked.connect(self.scanButtonClicked) self.loadResultsButton.clicked.connect(self.actionLoadResults.trigger) self.addFolderButton.clicked.connect(self.actionAddFolder.trigger) self.removeFolderButton.clicked.connect(self.removeFolderButtonClicked) self.treeView.selectionModel().selectionChanged.connect( self.selectionChanged) self.app.recentResults.itemsChanged.connect( self._updateLoadResultsButton) self.recentFolders.itemsChanged.connect(self._updateAddButton) self.recentFolders.mustOpenItem.connect(self.app.model.add_directory) self.directoriesModel.foldersAdded.connect( self.directoriesModelAddedFolders) self.app.willSavePrefs.connect(self.appWillSavePrefs) def _setupActions(self): # (name, shortcut, icon, desc, func) ACTIONS = [ ('actionLoadResults', 'Ctrl+L', '', tr("Load Results..."), self.loadResultsTriggered), ('actionShowResultsWindow', '', '', tr("Results Window"), self.app.showResultsWindow), ('actionAddFolder', '', '', tr("Add Folder..."), self.addFolderTriggered), ] createActions(ACTIONS, self) def _setupMenu(self): self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 42, 22)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle(tr("File")) self.menuView = QMenu(self.menubar) self.menuView.setTitle(tr("View")) self.menuHelp = QMenu(self.menubar) self.menuHelp.setTitle(tr("Help")) self.menuLoadRecent = QMenu(self.menuFile) self.menuLoadRecent.setTitle(tr("Load Recent Results")) self.setMenuBar(self.menubar) self.menuFile.addAction(self.actionLoadResults) self.menuFile.addAction(self.menuLoadRecent.menuAction()) self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionQuit) self.menuView.addAction(self.app.actionPreferences) self.menuView.addAction(self.actionShowResultsWindow) self.menuView.addAction(self.app.actionIgnoreList) self.menuHelp.addAction(self.app.actionShowHelp) self.menuHelp.addAction(self.app.actionOpenDebugLog) self.menuHelp.addAction(self.app.actionAbout) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) # Recent folders menu self.menuRecentFolders = QMenu() self.menuRecentFolders.addAction(self.actionAddFolder) self.menuRecentFolders.addSeparator() # Recent results menu self.menuRecentResults = QMenu() self.menuRecentResults.addAction(self.actionLoadResults) self.menuRecentResults.addSeparator() def _setupUi(self): self.setWindowTitle(self.app.NAME) self.resize(420, 338) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) self.promptLabel = QLabel( tr("Select folders to scan and press \"Scan\"."), self.centralwidget) self.verticalLayout.addWidget(self.promptLabel) self.treeView = QTreeView(self.centralwidget) self.treeView.setSelectionMode(QAbstractItemView.ExtendedSelection) self.treeView.setSelectionBehavior(QAbstractItemView.SelectRows) self.treeView.setAcceptDrops(True) triggers = QAbstractItemView.DoubleClicked|QAbstractItemView.EditKeyPressed\ |QAbstractItemView.SelectedClicked self.treeView.setEditTriggers(triggers) self.treeView.setDragDropOverwriteMode(True) self.treeView.setDragDropMode(QAbstractItemView.DropOnly) self.treeView.setUniformRowHeights(True) self.verticalLayout.addWidget(self.treeView) self.horizontalLayout = QHBoxLayout() self.removeFolderButton = QPushButton(self.centralwidget) self.removeFolderButton.setIcon(QIcon(QPixmap(":/minus"))) self.removeFolderButton.setShortcut("Del") self.horizontalLayout.addWidget(self.removeFolderButton) self.addFolderButton = QPushButton(self.centralwidget) self.addFolderButton.setIcon(QIcon(QPixmap(":/plus"))) self.horizontalLayout.addWidget(self.addFolderButton) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.loadResultsButton = QPushButton(self.centralwidget) self.loadResultsButton.setText(tr("Load Results")) self.horizontalLayout.addWidget(self.loadResultsButton) self.scanButton = QPushButton(self.centralwidget) self.scanButton.setText(tr("Scan")) self.scanButton.setDefault(True) self.horizontalLayout.addWidget(self.scanButton) self.verticalLayout.addLayout(self.horizontalLayout) self.setCentralWidget(self.centralwidget) self._setupActions() self._setupMenu() if self.app.prefs.directoriesWindowRect is not None: self.setGeometry(self.app.prefs.directoriesWindowRect) else: moveToScreenCenter(self) def _setupColumns(self): header = self.treeView.header() header.setStretchLastSection(False) header.setSectionResizeMode(0, QHeaderView.Stretch) header.setSectionResizeMode(1, QHeaderView.Fixed) header.resizeSection(1, 100) def _updateAddButton(self): if self.recentFolders.isEmpty(): self.addFolderButton.setMenu(None) else: self.addFolderButton.setMenu(self.menuRecentFolders) def _updateRemoveButton(self): indexes = self.treeView.selectedIndexes() if not indexes: self.removeFolderButton.setEnabled(False) return self.removeFolderButton.setEnabled(True) def _updateLoadResultsButton(self): if self.app.recentResults.isEmpty(): self.loadResultsButton.setMenu(None) else: self.loadResultsButton.setMenu(self.menuRecentResults) #--- QWidget overrides def closeEvent(self, event): event.accept() if self.app.model.results.is_modified: title = tr("Unsaved results") msg = tr("You have unsaved results, do you really want to quit?") if not self.app.confirm(title, msg): event.ignore() if event.isAccepted(): QApplication.quit() #--- Events def addFolderTriggered(self): title = tr("Select a folder to add to the scanning list") flags = QFileDialog.ShowDirsOnly dirpath = str( QFileDialog.getExistingDirectory(self, title, self.lastAddedFolder, flags)) if not dirpath: return self.lastAddedFolder = dirpath self.app.model.add_directory(dirpath) self.recentFolders.insertItem(dirpath) def appWillSavePrefs(self): self.app.prefs.directoriesWindowRect = self.geometry() def directoriesModelAddedFolders(self, folders): for folder in folders: self.recentFolders.insertItem(folder) def loadResultsTriggered(self): title = tr("Select a results file to load") files = ';;'.join( [tr("dupeGuru Results (*.dupeguru)"), tr("All Files (*.*)")]) destination = QFileDialog.getOpenFileName(self, title, '', files) if destination: self.app.model.load_from(destination) self.app.recentResults.insertItem(destination) def removeFolderButtonClicked(self): self.directoriesModel.model.remove_selected() def scanButtonClicked(self): if self.app.model.results.is_modified: title = tr("Start a new scan") msg = tr( "You have unsaved results, do you really want to continue?") if not self.app.confirm(title, msg): return self.app.model.start_scanning() def selectionChanged(self, selected, deselected): self._updateRemoveButton()
def __init__(self, parent=None): super(Assembler, self).__init__(parent) self.resize(800, 600) self.filename = None self.filetuple = None self.dirty = False # Refers to Data Page only. self.nb = None centralwidget = QWidget(self) gridLayout = QGridLayout(centralwidget) self.tabWidget = QTabWidget(centralwidget) # textbox self.tab = QWidget() font = QFont() font.setFamily("Inconsolata") font.setPointSize(14) self.tab.setFont(font) gridLayout_3 = QGridLayout(self.tab) self.plainTextEdit = QPlainTextEdit(self.tab) self.plainTextEdit.installEventFilter(self) self.plainTextEdit.setAcceptDrops(True) gridLayout_3.addWidget(self.plainTextEdit, 0, 0, 1, 1) self.tabWidget.addTab(self.tab, "") self.tab_2 = QWidget() self.tab_2.setFont(font) gridLayout_2 = QGridLayout(self.tab_2) self.plainTextEdit_2 = QPlainTextEdit(self.tab_2) gridLayout_2.addWidget(self.plainTextEdit_2, 0, 0, 1, 1) self.tabWidget.addTab(self.tab_2, "") self.tab_3 = QWidget() self.tab_3.setFont(font) gridLayout_3 = QGridLayout(self.tab_3) self.checkbox = QCheckBox("Cloning genes by tailed primers (no pYPKa_A vectors constructed)") self.checkbox.setChecked(True) gridLayout_3.addWidget(self.checkbox, 0, 0, 0, 0) self.tabWidget.addTab(self.tab_3, "") gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) self.setCentralWidget(centralwidget) menubar = QMenuBar(self) menubar.setGeometry(QRect(0, 0, 800, 29)) menu_File = QMenu(menubar) self.menu_Solve = QMenu(menubar) self.menu_Help = QMenu(menubar) self.setMenuBar(menubar) self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.action_New = QAction(self) self.actionSave_As = QAction(self) self.action_Save = QAction(self) self.action_Open = QAction(self) self.action_Quit = QAction(self) self.action_About = QAction(self) self.actionShow_CCPL = QAction(self) self.action_Solve = QAction(self) self.action_OpenNB = QAction(self) self.action_CCPL = QAction(self) self.action_Help = QAction(self) menu_File.addAction(self.action_New) menu_File.addAction(self.action_Open) menu_File.addAction(self.actionSave_As) menu_File.addAction(self.action_Save) menu_File.addSeparator() menu_File.addAction(self.action_Quit) self.menu_Solve.addAction(self.action_Solve) self.menu_Solve.addAction(self.action_OpenNB) self.menu_Help.addAction(self.action_About) #self.menu_Help.addAction(self.action_CCPL) #self.menu_Help.addAction(self.action_Help) menubar.addAction(menu_File.menuAction()) menubar.addAction(self.menu_Solve.menuAction()) menubar.addAction(self.menu_Help.menuAction()) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab),\ "Data Page") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2),\ "Assembly log") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3),\ "Settings") menu_File.setTitle("&File") self.menu_Solve.setTitle("&Assemble") self.menu_Help.setTitle("&About") self.tabWidget.setCurrentIndex(0) self.action_New.setText("&New") self.action_Open.setText("&Open") self.actionSave_As.setText("Save &As") self.action_Save.setText("&Save") self.action_Quit.setText("&Quit") self.action_Solve.setText("&Assemble") self.action_OpenNB.setText("&Open &pathway") self.action_About.setText("&About") #self.action_CCPL.setText("&CCPL") #self.action_Help.setText("&Help") self.action_Quit.triggered.connect(self.close) allToolBar = self.addToolBar("AllToolBar") allToolBar.setObjectName("AllToolBar") self.addActions(allToolBar, (self.action_Open, self.actionSave_As, self.action_Save, self.action_Solve, self.action_OpenNB, self.action_Quit )) self.action_New.triggered.connect(self.fileNew) self.action_Open.triggered.connect(self.fileOpen) self.actionSave_As.triggered.connect(self.fileSaveAs) self.action_Save.triggered.connect(self.fileSave) self.action_Solve.triggered.connect(self.solveAssembly) self.action_OpenNB.triggered.connect(self.openNB) self.action_About.triggered.connect(self.aboutBox) #self.action_CCPL.triggered.connect(self.displayCCPL) #self.action_Help.triggered.connect(self.help) self.plainTextEdit.textChanged.connect(self.setDirty) self.action_New = self.editAction(self.action_New, None,\ 'ctrl+N', 'filenew', 'New File.') self.action_Open = self.editAction(self.action_Open, None, 'ctrl+O', 'fileopen', 'Open File.') self.actionSave_As = self.editAction(self.actionSave_As,\ None, 'ctrl+A', 'filesaveas',\ 'Save and Name File.') self.action_Save = self.editAction(self.action_Save, None, 'ctrl+S', 'filesave', 'Save File.') self.action_Solve = self.editAction(self.action_Solve, None, '', 'solve', 'Assemble.') self.action_OpenNB = self.editAction(self.action_OpenNB, None, '', 'ipynb', 'Open pathway.') self.action_About = self.editAction(self.action_About, None, 'ctrl+B', 'about','Pop About Box.') self.action_CCPL = self.editAction(self.action_CCPL, None, 'ctrl+G', 'licence', 'Show Licence') self.action_Help = self.editAction(self.action_Help, None, 'ctrl+H', 'help', 'Show Help Page.') self.action_Quit = self.editAction(self.action_Quit, None, 'ctrl+Q', 'quit', 'Quit the program.') self.plainTextEdit_2.setReadOnly(True) self.setWindowTitle("ypkpathway") self.setWindowIcon(QIcon( resource_filename("ypkpathway","icons/ypkpathway.png"))) self.plainTextEdit.setFocus()
class EditorMainWindow(QMainWindow): def __init__(self): super().__init__() self.setupUi(self) self.retranslateUi(self) self.level = None path = get_default_path() if path is None: self.default_path = "" else: self.default_path = path self.dragging = False self.last_x = None self.last_y = None self.dragged_time = None self.deleting_item = False # Hack for preventing focusing on next item after deleting the previous one self.moving = False self.resetting = False self.entity_list_widget.currentItemChanged.connect(self.action_listwidget_change_selection) self.button_zoom_in.pressed.connect(self.zoom_in) self.button_zoom_out.pressed.connect(self.zoom_out) self.button_remove_entity.pressed.connect(self.remove_position) self.button_move_entity.pressed.connect(self.move_entity) self.button_clone_entity.pressed.connect(self.action_clone_entity) self.button_show_passengers.pressed.connect(self.action_passenger_window) self.button_edit_xml.pressed.connect(self.action_open_xml_editor) self.button_edit_base_xml.pressed.connect(self.action_open_basexml_editor) self.lineedit_angle.editingFinished.connect(self.action_lineedit_changeangle) self.bw_map_screen.mouse_clicked.connect(self.get_position) self.bw_map_screen.entity_clicked.connect(self.entity_position) self.bw_map_screen.mouse_dragged.connect(self.mouse_move) self.bw_map_screen.mouse_released.connect(self.mouse_release) self.bw_map_screen.mouse_wheel.connect(self.mouse_wheel_scroll_zoom) status = self.statusbar self.bw_map_screen.setMouseTracking(True) self.passenger_window = BWPassengerWindow() self.passenger_window.passengerlist.currentItemChanged.connect(self.passengerwindow_action_choose_entity) self.xmlobject_textbox = BWEntityXMLEditor() self.xmlobject_textbox.button_xml_savetext.pressed.connect(self.xmleditor_action_save_object_xml) self.xmlobject_textbox.triggered.connect(self.action_open_xml_editor_unlimited) self.basexmlobject_textbox = BWEntityXMLEditor(windowtype="XML Base Object") self.basexmlobject_textbox.button_xml_savetext.pressed.connect(self.xmleditor_action_save_base_object_xml) self.basexmlobject_textbox.triggered.connect(self.action_open_xml_editor_unlimited) self.types_visible = {} self.terrain_image = None status.showMessage("Ready") self.xml_windows = {} print("We are now ready!") def reset(self): self.resetting = True self.statusbar.clearMessage() self.dragged_time = None self.moving = False self.dragging = False self.last_x = None self.last_y = None self.dragged_time = None self.moving = False self.entity_list_widget.clearSelection() self.entity_list_widget.clear() self.bw_map_screen.reset() self.clear_visibility_toggles() for window in (self.passenger_window, self.xmlobject_textbox, self.basexmlobject_textbox): window.close() window.reset() for id in self.xml_windows: self.destroy_xml_editor(id) self.resetting = False print("reset done") def destroy_xml_editor(self, id): pass @catch_exception def open_xml_editor(self, objectid, offsetx=0, offsety=0): selected = objectid if self.level is not None and selected in self.level.obj_map: delete = [] for objid, window in self.xml_windows.items(): if not window.isVisible() and objid != selected: window.destroy() delete.append(objid) for objid in delete: del self.xml_windows[objid] if selected == self.basexmlobject_textbox.entity or selected == self.xmlobject_textbox.entity: pass # No need to make a new window elif selected in self.xml_windows and self.xml_windows[selected].isVisible(): self.xml_windows[selected].activateWindow() self.xml_windows[selected].update() else: xml_window = BWEntityXMLEditor() def xmleditor_save_object_unlimited(): self.statusbar.showMessage("Saving object changes...") try: xmlnode = xml_window.get_content() #assert self.bw_map_screen.current_entity == self.basexmlobject_textbox.entity assert xml_window.entity == xmlnode.get("id") # Disallow changing the id of the base object self.level.remove_object(xmlnode.get("id")) self.level.add_object(xmlnode) self.statusbar.showMessage("Saved base object {0} as {1}".format( xml_window.entity, self.level.obj_map[xmlnode.get("id")].name)) except: self.statusbar.showMessage("Saving object failed") traceback.print_exc() xml_window.button_xml_savetext.pressed.connect(xmleditor_save_object_unlimited) xml_window.triggered.connect(self.action_open_xml_editor_unlimited) obj = self.level.obj_map[selected] xml_window.set_title(obj.name) xml_window.set_content(obj._xml_node) #xml_window.move(QPoint(xml_editor_owner.pos().x()+20, xml_editor_owner.pos().y()+20)) xml_window.move(QPoint(offsetx, offsety)) xml_window.show() xml_window.update() self.xml_windows[selected] = xml_window @catch_exception def action_open_xml_editor_unlimited(self, xml_editor_owner): selected = xml_editor_owner.textbox_xml.textCursor().selectedText() self.open_xml_editor(selected, offsetx=xml_editor_owner.pos().x()+20, offsety=xml_editor_owner.pos().y()+20) @catch_exception def action_open_basexml_editor(self): """ if not self.basexmlobject_textbox.isVisible(): self.basexmlobject_textbox.destroy() self.basexmlobject_textbox = BWEntityXMLEditor(windowtype="XML Base Object") self.basexmlobject_textbox.button_xml_savetext.pressed.connect(self.xmleditor_action_save_base_object_xml) self.basexmlobject_textbox.triggered.connect(self.action_open_xml_editor_unlimited) self.basexmlobject_textbox.show() self.basexmlobject_textbox.activateWindow()""" if self.level is not None and self.bw_map_screen.current_entity is not None: obj = self.level.obj_map[self.bw_map_screen.current_entity] if not obj.has_attr("mBase"): pass else: baseobj = self.level.obj_map[obj.get_attr_value("mBase")] #self.basexmlobject_textbox.set_title(baseobj.id) self.open_xml_editor(baseobj.id) def xmleditor_action_save_base_object_xml(self): self.statusbar.showMessage("Saving base object changes...") try: xmlnode = self.basexmlobject_textbox.get_content() #assert self.bw_map_screen.current_entity == self.basexmlobject_textbox.entity assert self.basexmlobject_textbox.entity == xmlnode.get("id") # Disallow changing the id of the base object self.level.remove_object(xmlnode.get("id")) self.level.add_object(xmlnode) self.statusbar.showMessage("Saved base object {0} as {1}".format( self.basexmlobject_textbox.entity, self.level.obj_map[xmlnode.get("id")].name)) except: self.statusbar.showMessage("Saving base object failed") traceback.print_exc() def action_open_xml_editor(self): """ if not self.xmlobject_textbox.isVisible(): self.xmlobject_textbox.destroy() self.xmlobject_textbox = BWEntityXMLEditor() self.xmlobject_textbox.button_xml_savetext.pressed.connect(self.xmleditor_action_save_object_xml) self.xmlobject_textbox.triggered.connect(self.action_open_xml_editor_unlimited) self.xmlobject_textbox.show() self.xmlobject_textbox.activateWindow()""" if self.level is not None and self.bw_map_screen.current_entity is not None: entityobj = self.level.obj_map[self.bw_map_screen.current_entity] self.open_xml_editor(objectid=entityobj.id) update_mapscreen(self.bw_map_screen, self.level.obj_map[entityobj.id]) self.bw_map_screen.update() """self.xmlobject_textbox.set_title(entityobj.id) self.xmlobject_textbox.set_content(entityobj._xml_node) self.xmlobject_textbox.update()""" def xmleditor_action_save_object_xml(self): self.statusbar.showMessage("Saving object changes...") try: xmlnode = self.xmlobject_textbox.get_content() #assert self.bw_map_screen.current_entity == self.xmlobject_textbox.entity assert self.xmlobject_textbox.entity == xmlnode.get("id") or xmlnode.get("id") not in self.level.obj_map if self.passenger_window.isVisible(): self.passenger_window.close() if self.xmlobject_textbox.entity != xmlnode.get("id"): #obj = self.level.obj_map[xmlnode.get("id")] self.level.remove_object(self.xmlobject_textbox.entity) print("adding", xmlnode.get("id"), xmlnode.get("id") in self.level.obj_map ) self.level.add_object(xmlnode) pos = self.get_entity_item_pos(self.xmlobject_textbox.entity) item = self.entity_list_widget.takeItem(pos) self.entity_list_widget.removeItemWidget(item) self.add_item_sorted(xmlnode.get("id")) self.bw_map_screen.rename_entity(self.xmlobject_textbox.entity, xmlnode.get("id")) assert xmlnode.get("id") in self.level.obj_map self.xmlobject_textbox.entity = xmlnode.get("id") self.xmlobject_textbox.set_title(xmlnode.get("id")) else: self.level.remove_object(xmlnode.get("id")) self.level.add_object(xmlnode) update_mapscreen(self.bw_map_screen, self.level.obj_map[xmlnode.get("id")]) self.statusbar.showMessage("Saved object {0} as {1}".format( self.xmlobject_textbox.entity, self.level.obj_map[xmlnode.get("id")].name)) self.bw_map_screen.update() except: self.statusbar.showMessage("Saving object failed") traceback.print_exc() def action_clone_entity(self): entities = [] if self.bw_map_screen.current_entity is not None: entities.append(self.bw_map_screen.current_entity) elif len(self.bw_map_screen.selected_entities) > 0: entities.extend(self.bw_map_screen.selected_entities.keys()) if len(entities) > 0: dont_clone = {} for entity in entities: obj = self.level.obj_map[entity] if obj.has_attr("mPassenger"): passengers = obj.get_attr_elements("mPassenger") for passenger in passengers: if passenger != "0": dont_clone[passenger] = True select = [] for entity in entities: if entity in dont_clone: continue obj = self.level.obj_map[entity] xml_node = deepcopy(obj._xml_node) try: cloned_id = self.level.generate_unique_id(entity) xml_node.set("id", cloned_id) self.level.add_object(xml_node) bw_x, bw_y, angle = object_get_position(self.level, cloned_id) x, y = bw_coords_to_image_coords(bw_x, bw_y) self.add_item_sorted(cloned_id) self.bw_map_screen.add_entity(x, y, cloned_id, obj.type) clonedobj = self.level.obj_map[cloned_id] select.append(cloned_id) update_mapscreen(self.bw_map_screen, clonedobj) if clonedobj.has_attr("mPassenger"): orig_x = bw_x orig_y = bw_y passengers = clonedobj.get_attr_elements("mPassenger") passengers_added = [] for i, passenger in enumerate(passengers): if passenger != "0": obj = self.level.obj_map[passenger] xml_node = deepcopy(obj._xml_node) clonedpassenger_id = self.level.generate_unique_id(passenger) xml_node.set("id", clonedpassenger_id) #print("orig passenger: {0}, new passenger: {1}, alreadyexists: {2}".format( # passenger, clonedpassenger_id, clonedpassenger_id in self.level.obj_map #)) #print(type(passenger), type(clonedpassenger_id)) self.level.add_object(xml_node) #x, y = object_get_position(self.level, newid) x = orig_x + (i+1)*8 y = orig_y + (i+1)*8 #print(orig_x, orig_y, x, y) object_set_position(self.level, clonedpassenger_id, x, y) x, y = bw_coords_to_image_coords(x, y) self.add_item_sorted(clonedpassenger_id) self.bw_map_screen.add_entity(x, y, clonedpassenger_id, obj.type) update_mapscreen(self.bw_map_screen, self.level.obj_map[clonedpassenger_id]) passengers_added.append(passenger) clonedobj.set_attr_value("mPassenger", clonedpassenger_id, i) select.append(clonedpassenger_id) #print("passengers added:", passengers_added) self.bw_map_screen.selected_entities = {} if len(select) == 1: ent = select[0] self.set_entity_text(ent) self.bw_map_screen.choose_entity(ent) else: for ent in select: self.bw_map_screen.selected_entities[ent] = True self.set_entity_text_multiple(self.bw_map_screen.selected_entities) self.bw_map_screen.update() except: traceback.print_exc() def add_item_sorted(self, entity): max_count = self.entity_list_widget.count() entityobj = self.level.obj_map[entity] index = 0 entity_item = BWEntityEntry(entity, "{0}[{1}]".format(entity, entityobj.type)) # Similar to loading a level, we add the entity in a sorted way by # creating this string and comparing it for every item in the list. entity_string = get_type(entityobj.type)+entityobj.type+entityobj.id inserted = False for i in range(max_count): curritem = self.entity_list_widget.item(i) currobj = self.level.obj_map[curritem.xml_ref] currstring = get_type(currobj.type)+currobj.type+currobj.id # The list is already sorted, so if we find an item bigger than # the one we are inserting, we know the position we have to insert the item in. # String comparison should be alpabetically. if currstring > entity_string: self.entity_list_widget.insertItem(i, entity_item) inserted = True break # If we couldn't insert the item, i.e. there are no items at all # or all items are smaller than the item we add, we just add it at the end. if not inserted: self.entity_list_widget.addItem(entity_item) def get_entity_item_pos(self, entityid): for i in range(self.entity_list_widget.count()): item = self.entity_list_widget.item(i) if item.xml_ref == entityid: return i return None def action_passenger_window(self): #if self.passenger_window.isVisible() print("window is visible: ", self.passenger_window.isVisible()) #self.passenger_window.reset() if not self.passenger_window.isVisible(): self.passenger_window.destroy() self.passenger_window = BWPassengerWindow() self.passenger_window.passengerlist.currentItemChanged.connect(self.passengerwindow_action_choose_entity) self.passenger_window.show() self.passenger_window.activateWindow() if self.bw_map_screen.current_entity is not None: self.passenger_window.reset() entityobj = self.level.obj_map[self.bw_map_screen.current_entity] self.passenger_window.set_title(entityobj.id) if entityobj.has_attr("mPassenger"): for i, passenger in enumerate(entityobj.get_attr_elements("mPassenger")): if passenger in self.level.obj_map: passengerobj = self.level.obj_map[passenger] list_item_name = "{0}[{1}]".format(passenger, passengerobj.type) elif passenger == "0": list_item_name = "{0}<none>".format(passenger) else: list_item_name = "{0}<missing>".format(passenger) self.passenger_window.add_passenger(list_item_name, passenger) self.passenger_window.update() def passengerwindow_action_choose_entity(self, current, previous): try: if current is not None and current.xml_ref in self.level.obj_map: self.set_entity_text(current.xml_ref) self.bw_map_screen.choose_entity(current.xml_ref) elif current is not None: self.statusbar.showMessage("No such entity: {0}".format(current.xml_ref), 1000*2) except: traceback.print_exc() def move_entity(self): if not self.dragging: if not self.moving: self.moving = True currtext = self.button_move_entity.text() self.button_move_entity.setText("Stop [Move Entity]") else: self.moving = False currtext = "Move Entity" self.button_move_entity.setText(currtext) def button_load_level(self): try: print("ok", self.default_path) self.xmlPath = "" filepath, choosentype = QFileDialog.getOpenFileName( self, "Open File", self.default_path, BW_LEVEL+";;"+BW_COMPRESSED_LEVEL+";;All files (*)") print("doooone") if filepath: print("resetting") self.reset() print("done") print("chosen type:",choosentype) # Some BW levels are clear XML files, some are compressed with GZIP # We decide between the two either based on user choice or end of filepath if choosentype == BW_COMPRESSED_LEVEL or filepath.endswith(".gz"): print("OPENING AS COMPRESSED") file_open = gzip.open else: file_open = open with file_open(filepath, "rb") as f: try: self.level = BattWarsLevel(f) self.default_path = filepath set_default_path(filepath) self.setup_visibility_toggles() for obj_id, obj in sorted(self.level.obj_map.items(), key=lambda x: get_type(x[1].type)+x[1].type+x[1].id): #print("doing", obj_id) if get_position_attribute(obj) is None: continue #if not obj.has_attr("Mat"): # continue x, y, angle = object_get_position(self.level, obj_id) assert type(x) != str x, y = bw_coords_to_image_coords(x, y) item = BWEntityEntry(obj_id, "{0}[{1}]".format(obj_id, obj.type)) self.entity_list_widget.addItem(item) self.bw_map_screen.add_entity(x, y, obj_id, obj.type, update=False) #if obj.type == "cMapZone": update_mapscreen(self.bw_map_screen, obj) print("ok") self.bw_map_screen.update() path_parts = path.split(filepath) self.setWindowTitle("BW-MapEdit - {0}".format(path_parts[-1])) except Exception as error: print("error", error) traceback.print_exc() except Exception as er: print("errrorrr", er) traceback.print_exc() print("loaded") def button_save_level(self): if self.level is not None: filepath, choosentype = QFileDialog.getSaveFileName( self, "Save File", self.default_path, BW_LEVEL+";;"+BW_COMPRESSED_LEVEL+";;All files (*)") print(filepath, "saved") if filepath: # Simiar to load level if choosentype == BW_COMPRESSED_LEVEL or filepath.endswith(".gz"): file_open = gzip.open else: file_open = open try: with file_open(filepath, "wb") as f: self.level._tree.write(f) except Exception as error: print("COULDN'T SAVE:", error) traceback.print_exc() self.default_path = filepath else: pass # no level loaded, do nothing def entity_position(self, event, entity): try: # Make it possible to select objects in move mode, but don't make it too easy to lose # a selection. if not (self.moving and len(self.bw_map_screen.selected_entities) > 1): print("got entity:",entity, self.bw_map_screen.entities[entity][2]) print(entity_get_model(self.level, entity)) self.set_entity_text(entity) self.bw_map_screen.choose_entity(entity) pos = self.get_entity_item_pos(entity) print("searching:",pos) try: self.entity_list_widget.select_item(pos) except: traceback.print_exc() self.bw_map_screen.selected_entities = {} self.bw_map_screen.update() except: traceback.print_exc() def remove_position(self): #self.bw_map_screen.entities.pop() try: # Remove the entity from the map, the list widget and the level data self.deleting_item = True entities = [] if self.bw_map_screen.current_entity is not None: entities.append(self.bw_map_screen.current_entity) elif len(self.bw_map_screen.selected_entities) > 0: entities.extend(self.bw_map_screen.selected_entities.keys()) self.bw_map_screen.selected_entities = {} self.set_entity_text_multiple(self.bw_map_screen.selected_entities) if len(entities) > 0: for entity in entities: pos = self.get_entity_item_pos(entity) item = self.entity_list_widget.takeItem(pos) assert item.xml_ref == entity #self.entity_list_widget.clearSelection() self.entity_list_widget.clearFocus() self.entity_list_widget.removeItemWidget(item) self.level.remove_object(entity) self.bw_map_screen.remove_entity(entity) self.bw_map_screen.update() except: traceback.print_exc() raise #@catch_exception def get_position(self, event): self.dragging = True self.last_x = event.x() self.last_y = event.y() self.dragged_time = default_timer() mouse_x = event.x()/self.bw_map_screen.zoom_factor mouse_y = event.y()/self.bw_map_screen.zoom_factor if event.buttons() == QtCore.Qt.LeftButton: if not self.moving: self.bw_map_screen.set_selectionbox_start((event.x(), event.y())) else: if self.bw_map_screen.current_entity is not None: newx, newy = image_coords_to_bw_coords(mouse_x, mouse_y) object_set_position(self.level, self.bw_map_screen.current_entity, newx, newy) self.bw_map_screen.move_entity(self.bw_map_screen.current_entity, mouse_x, mouse_y) self.set_entity_text(self.bw_map_screen.current_entity) update_mapscreen(self.bw_map_screen, self.level.obj_map[self.bw_map_screen.current_entity]) elif len(self.bw_map_screen.selected_entities) > 0: for entity in self.bw_map_screen.selected_entities: first_entity = entity break #first_entity = self.bw_map_screen.selected_entities.keys()[0] x, y, entitytype, metadata = self.bw_map_screen.entities[first_entity] startx = endx = x starty = endy = y for entity in self.bw_map_screen.selected_entities: x, y, dontneed, dontneed = self.bw_map_screen.entities[entity] if x < startx: startx = x if x > endx: endx = x if y < starty: starty = y if y > endy: endy = y middle_x = (startx+endx) / 2 middle_y = (starty+endy) / 2 delta_x = mouse_x - middle_x delta_y = mouse_y - middle_y for entity in self.bw_map_screen.selected_entities: x, y, dontneed, dontneed = self.bw_map_screen.entities[entity] newx, newy = image_coords_to_bw_coords(x+delta_x, y+delta_y) object_set_position(self.level, entity, newx, newy) self.bw_map_screen.move_entity(entity, x+delta_x, y+delta_y) #self.set_entity_text(self.bw_map_screen.current_entity) update_mapscreen(self.bw_map_screen, self.level.obj_map[entity]) self.bw_map_screen.update() @catch_exception def mouse_move(self, event): x, y = image_coords_to_bw_coords(event.x()/self.bw_map_screen.zoom_factor, event.y()/self.bw_map_screen.zoom_factor) self.statusbar.showMessage("x: {0} y: {1}".format(round(x, 5), round(y, 5))) if self.dragging and default_timer() - self.dragged_time > 0.1: if event.buttons() == QtCore.Qt.RightButton: delta_x = (event.x()-self.last_x)/8 delta_y = (event.y()-self.last_y)/8 #print("hi",event.x(), event.y()) vertbar = self.scrollArea.verticalScrollBar() horizbar = self.scrollArea.horizontalScrollBar() vertbar.setSliderPosition(vertbar.value()-delta_y) horizbar.setSliderPosition(horizbar.value()-delta_x) elif event.buttons() == QtCore.Qt.LeftButton: self.bw_map_screen.set_selectionbox_end((event.x(), event.y())) if len(self.bw_map_screen.selected_entities) > 0 or self.bw_map_screen.current_entity is None: self.bw_map_screen.choose_entity(None) self.set_entity_text_multiple(self.bw_map_screen.selected_entities) self.bw_map_screen.update() def mouse_release(self, event): self.dragging = False if self.bw_map_screen.selectionbox_end is not None: self.bw_map_screen.clear_selection_box() self.bw_map_screen.update() def set_entity_text_multiple(self, entities): self.label_object_id.setText("{0} objects selected".format(len(entities))) MAX = 15 listentities = [self.level.obj_map[x].name for x in sorted(entities.keys())][0:MAX] listentities.sort() if len(entities) > MAX: listentities.append("... and {0} more".format(len(entities) - len(listentities))) self.label_position.setText("\n".join(listentities[:5])) self.label_model_name.setText("\n".join(listentities[5:10])) self.label_4.setText("\n".join(listentities[10:]))#15])) self.label_5.setText("")#("\n".join(listentities[12:16])) def set_entity_text(self, entityid): try: obj = self.level.obj_map[entityid] if obj.has_attr("mBase"): base = self.level.obj_map[obj.get_attr_value("mBase")] self.label_object_id.setText("{0}\n[{1}]\nBase: {2}\n[{3}]".format( entityid, obj.type, base.id, base.type)) else: self.label_object_id.setText("{0}\n[{1}]".format(entityid, obj.type)) self.label_model_name.setText("Model: {0}".format(entity_get_model(self.level, entityid))) x, y, angle = object_get_position(self.level, entityid) self.label_position.setText("x: {0}\ny: {1}".format(x, y)) self.lineedit_angle.setText(str(round(angle,2))) self.label_4.setText("Army: {0}".format(entity_get_army(self.level, entityid))) if not obj.has_attr("mPassenger"): self.label_5.setText("Icon Type: \n{0}".format(entity_get_icon_type(self.level, entityid))) else: passengers = 0 for passenger in obj.get_attr_elements("mPassenger"): if passenger != "0": passengers += 1 self.label_5.setText("Icon Type: \n{0}\n\nPassengers: {1}".format( entity_get_icon_type(self.level, entityid), passengers)) except: traceback.print_exc() def action_listwidget_change_selection(self, current, previous): #QtWidgets.QListWidgetItem. if not self.resetting and current is not None: print("ok") print("hi", current.text(), current.xml_ref) self.set_entity_text(current.xml_ref) self.bw_map_screen.choose_entity(current.xml_ref) posx, posy, typename, metadata = self.bw_map_screen.entities[current.xml_ref] zf = self.bw_map_screen.zoom_factor try: if not self.deleting_item: x_margin = min(100, 50*zf) y_margin = min(100, 50*zf) self.scrollArea.ensureVisible(posx*zf, posy*zf, xMargin=x_margin, yMargin=y_margin) else: self.deleting_item = False except: traceback.print_exc() def zoom_out(self, noslider=False): horizbar = self.scrollArea.horizontalScrollBar() vertbar = self.scrollArea.verticalScrollBar() print(horizbar.maximum(), vertbar.maximum()) if horizbar.maximum() > 0: widthratio = horizbar.value()/horizbar.maximum() else: widthratio = 0 if vertbar.maximum() > 0: heightratio = vertbar.value()/vertbar.maximum() else: heightratio = 0 #oldzf = self.bw_map_screen.zoom_factor / (0.1+1) #diff = oldzf - self.bw_map_screen.zoom_factor zf = self.bw_map_screen.zoom_factor self.bw_map_screen.zoom(calc_zoom_out_factor(zf))#diff) # if not noslider: horizbar.setSliderPosition(horizbar.maximum()*widthratio) vertbar.setSliderPosition(vertbar.maximum()*heightratio) self.bw_map_screen.update() self.statusbar.showMessage("Zoom: {0}x".format(self.bw_map_screen.zoom_factor)) def zoom_in(self, noslider=False): horizbar = self.scrollArea.horizontalScrollBar() vertbar = self.scrollArea.verticalScrollBar() if horizbar.maximum() > 0: widthratio = horizbar.value()/horizbar.maximum() else: widthratio = 0 if vertbar.maximum() > 0: heightratio = vertbar.value()/vertbar.maximum() else: heightratio = 0 zf = self.bw_map_screen.zoom_factor self.bw_map_screen.zoom(calc_zoom_in_factor(zf))#zf) # print("wedidit?") if not noslider: horizbar.setSliderPosition(horizbar.maximum()*widthratio) vertbar.setSliderPosition(vertbar.maximum()*heightratio) self.bw_map_screen.update() self.statusbar.showMessage("Zoom: {0}x".format(self.bw_map_screen.zoom_factor)) @catch_exception def mouse_wheel_scroll_zoom(self, wheel_event): print("scrolling", wheel_event) print("Scroll", wheel_event.x(), wheel_event.y(), wheel_event.angleDelta().y())#, wheel_event.delta()) wheel_delta = wheel_event.angleDelta().y() zf = self.bw_map_screen.zoom_factor norm_x = wheel_event.x()/zf norm_y = wheel_event.y()/zf if wheel_delta > 0: if zf <= 10: self.zoom_in(True) zf = self.bw_map_screen.zoom_factor xmargin = self.scrollArea.viewport().width()//2 - 200 ymargin = self.scrollArea.viewport().height()//2 - 200 self.scrollArea.ensureVisible(norm_x*zf, norm_y*zf, xmargin, ymargin) self.bw_map_screen.update() else: self.zoom_in() elif wheel_delta < 0: self.zoom_out() def action_lineedit_changeangle(self): if not self.resetting and self.bw_map_screen.current_entity is not None: print("ok") current = self.bw_map_screen.current_entity currx, curry, angle = object_get_position(self.level, current) newangle = self.lineedit_angle.text().strip() print(newangle, newangle.isdecimal()) try: angle = float(newangle) object_set_position(self.level, current, currx, curry, angle=angle) currentobj = self.level.obj_map[current] update_mapscreen(self.bw_map_screen, currentobj) self.bw_map_screen.update() except: traceback.print_exc() def button_terrain_load_action(self): try: print("ok", self.default_path) filepath, choosentype = QFileDialog.getOpenFileName( self, "Open File", self.default_path, "BW terrain files (*.out *out.gz);;All files (*)") print("doooone") if filepath: if filepath.endswith(".gz"): file_open = gzip.open else: file_open = open with file_open(filepath, "rb") as f: try: terrain = BWArchiveBase(f) if self.level is not None: waterheight = get_water_height(self.level) else: waterheight = None image, light_image = parse_terrain_to_image(terrain, waterheight) self.bw_map_screen.set_terrain(image, light_image) except: traceback.print_exc() except: traceback.print_exc() def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(820, 760) MainWindow.setMinimumSize(QSize(720, 560)) MainWindow.setWindowTitle("BW-MapEdit") #MainWindow.setWindowTitle("Nep-Nep") self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") MainWindow.setCentralWidget(self.centralwidget) self.horizontalLayout = QHBoxLayout(self.centralwidget) self.horizontalLayout.setObjectName("horizontalLayout") self.scrollArea = QScrollArea(self.centralwidget) self.scrollArea.setWidgetResizable(True) self.bw_map_screen = BWMapViewer(self.centralwidget) self.scrollArea.setWidget(self.bw_map_screen) self.horizontalLayout.addWidget(self.scrollArea) #self.horizontalLayout.addWidget(self.bw_map_screen) self.entity_list_widget = BWEntityListWidget(self.centralwidget) self.entity_list_widget.setMaximumSize(QSize(300, 16777215)) self.entity_list_widget.setObjectName("entity_list_widget") self.horizontalLayout.addWidget(self.entity_list_widget) spacerItem = QSpacerItem(10, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.horizontalLayout.addItem(spacerItem) self.vertLayoutWidget = QWidget(self.centralwidget) self.vertLayoutWidget.setMaximumSize(QSize(250, 1200)) self.verticalLayout = QVBoxLayout(self.vertLayoutWidget) self.verticalLayout.setObjectName("verticalLayout") #self.verticalLayout. self.button_clone_entity = QPushButton(self.centralwidget) self.button_clone_entity.setObjectName("button_clone_entity") self.verticalLayout.addWidget(self.button_clone_entity) self.button_remove_entity = QPushButton(self.centralwidget) self.button_remove_entity.setObjectName("button_remove_entity") self.verticalLayout.addWidget(self.button_remove_entity) self.button_move_entity = QPushButton(self.centralwidget) self.button_move_entity.setObjectName("button_move_entity") self.verticalLayout.addWidget(self.button_move_entity) self.button_show_passengers = QPushButton(self.centralwidget) self.button_show_passengers.setObjectName("button_move_entity") self.verticalLayout.addWidget(self.button_show_passengers) self.gridLayout = QGridLayout() self.gridLayout.setObjectName("gridLayout") self.button_zoom_in = QPushButton(self.centralwidget) self.button_zoom_in.setObjectName("button_zoom_in") self.gridLayout.addWidget(self.button_zoom_in, 0, 0, 0, 1) self.button_zoom_out = QPushButton(self.centralwidget) self.button_zoom_out.setObjectName("button_zoom_out") self.gridLayout.addWidget(self.button_zoom_out, 0, 1, 0, 1) self.button_edit_xml = QPushButton(self.centralwidget) self.button_edit_xml.setObjectName("button_edit_xml") self.button_edit_base_xml = QPushButton(self.centralwidget) self.button_edit_base_xml.setObjectName("button_edit_base_xml") self.verticalLayout.addLayout(self.gridLayout) self.verticalLayout.addWidget(self.button_edit_xml) self.verticalLayout.addWidget(self.button_edit_base_xml) spacerItem1 = QSpacerItem(10, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.verticalLayout.addItem(spacerItem1) self.verticalLayout_2 = QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.lineedit_angle = QLineEdit(self.centralwidget) self.lineedit_angle.setObjectName("lineedit_angle") self.lineedit_angle.setPlaceholderText("Angle") self.label_object_id = QLabel(self.centralwidget) self.label_object_id.setObjectName("label_object_id") #TextSelectableByCursor self.label_position = QLabel(self.centralwidget) self.label_position.setObjectName("label_position") self.label_model_name = QLabel(self.centralwidget) self.label_model_name.setObjectName("label_model_name") self.label_4 = QLabel(self.centralwidget) self.label_4.setObjectName("label_4") self.label_5 = QLabel(self.centralwidget) self.label_5.setObjectName("label_5") for label in (self.label_object_id, self.label_position, self.label_model_name, self.label_4, self.label_5): label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse) self.verticalLayout_2.addWidget(self.lineedit_angle) self.verticalLayout_2.addWidget(self.label_object_id) self.verticalLayout_2.addWidget(self.label_position) self.verticalLayout_2.addWidget(self.label_model_name) self.verticalLayout_2.addWidget(self.label_4) self.verticalLayout_2.addWidget(self.label_5) self.verticalLayout.addLayout(self.verticalLayout_2) self.horizontalLayout.addWidget(self.vertLayoutWidget) self.menubar = QMenuBar(MainWindow) self.menubar.setGeometry(QRect(0, 0, 820, 29)) self.menubar.setObjectName("menubar") self.file_menu = QMenu(self.menubar) self.file_menu.setObjectName("menuLoad") self.file_load_action = QAction("Load", self) self.file_load_action.triggered.connect(self.button_load_level) self.file_menu.addAction(self.file_load_action) self.file_save_action = QAction("Save", self) self.file_save_action.triggered.connect(self.button_save_level) self.file_menu.addAction(self.file_save_action) self.visibility_menu = MenuDontClose(self.menubar)#QMenu(self.menubar) self.visibility_menu.setObjectName("visibility") #self.visibility_menu.addAction(self.toggle_action) self.visibility_actions = [] self.terrain_menu = QMenu(self.menubar) self.terrain_menu.setObjectName("terrain") self.terrain_load_action = QAction("Load Terrain", self) self.terrain_load_action.triggered.connect(self.button_terrain_load_action) self.terrain_menu.addAction(self.terrain_load_action) self.terrain_display_actions = [] self.setup_terrain_display_toggles() #self.menuLoad_2 = QMenu(self.menubar) #self.menuLoad_2.setObjectName("menuLoad_2") MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.menubar.addAction(self.file_menu.menuAction()) #self.menubar.addAction(self.menuLoad_2.menuAction()) self.menubar.addAction(self.visibility_menu.menuAction()) self.menubar.addAction(self.terrain_menu.menuAction()) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) def make_terrain_toggle(self, show_mode): def terraintoggle(toggled): print("I am", show_mode, "and I was pressed") if toggled is True: for action, toggle, mode in self.terrain_display_actions: if mode != show_mode: action.setChecked(False) self.bw_map_screen.set_show_terrain_mode(show_mode) elif toggled is False: self.bw_map_screen.set_show_terrain_mode(SHOW_TERRAIN_NO_TERRAIN) else: print("This shouldn't be possible", toggled, type(toggled)) self.bw_map_screen.update() return terraintoggle def setup_terrain_display_toggles(self): for mode, name in ((SHOW_TERRAIN_REGULAR, "Show Heightmap"), (SHOW_TERRAIN_LIGHT, "Show Lightmap")): toggle = self.make_terrain_toggle(mode) toggle_action = QAction(name, self) toggle_action.setCheckable(True) if mode == SHOW_TERRAIN_REGULAR: toggle_action.setChecked(True) else: toggle_action.setChecked(False) toggle_action.triggered.connect(toggle) self.terrain_menu.addAction(toggle_action) self.terrain_display_actions.append((toggle_action, toggle, mode)) def clear_terrain_toggles(self): try: for action, func, mode in self.terrain_display_actions: self.terrain_menu.removeAction(action) self.terrain_display_actions = [] except: traceback.print_exc() def make_toggle_function(self, objtype): def toggle(toggled): print("i was pressed") my_type = copy(objtype) self.types_visible[my_type] = toggled self.bw_map_screen.set_visibility(self.types_visible) self.bw_map_screen.update() return toggle def setup_visibility_toggles(self): for objtype in sorted(self.level.objtypes_with_positions): toggle = self.make_toggle_function(objtype) toggle_action = QAction(copy(objtype), self) toggle_action.setCheckable(True) toggle_action.setChecked(True) toggle_action.triggered.connect(toggle) self.types_visible[objtype] = True self.visibility_menu.addAction(toggle_action) self.visibility_actions.append((toggle_action, toggle)) toggle_all = QAction("Toggle All", self) toggle_all.triggered.connect(self.toggle_visiblity_all) self.visibility_menu.addAction(toggle_all) self.visibility_actions.append((toggle_all, self.toggle_visiblity_all)) def toggle_visiblity_all(self): for action, func in self.visibility_actions: if action.isCheckable(): objtype = action.text() toggle = self.types_visible[objtype] self.types_visible[objtype] = not toggle action.setChecked(not toggle) self.bw_map_screen.set_visibility(self.types_visible) self.bw_map_screen.update() def clear_visibility_toggles(self): try: for action, func in self.visibility_actions: self.visibility_menu.removeAction(action) self.visibility_actions = [] self.types_visible = {} except: traceback.print_exc() def retranslateUi(self, MainWindow): _translate = QCoreApplication.translate self.button_clone_entity.setText(_translate("MainWindow", "Clone Entity")) self.button_remove_entity.setText(_translate("MainWindow", "Delete Entity")) self.button_move_entity.setText(_translate("MainWindow", "Move Entity")) self.button_zoom_in.setText(_translate("MainWindow", "Zoom In")) self.button_zoom_out.setText(_translate("MainWindow", "Zoom Out")) self.button_show_passengers.setText(_translate("MainWindow", "Show Passengers")) self.button_edit_xml.setText("Edit Object XML") self.button_edit_base_xml.setText("Edit Base Object XML") self.label_model_name.setText(_translate("MainWindow", "TextLabel1")) self.label_object_id.setText(_translate("MainWindow", "TextLabel2")) self.label_position.setText(_translate("MainWindow", "TextLabel3")) self.label_4.setText(_translate("MainWindow", "TextLabel4")) self.label_5.setText(_translate("MainWindow", "TextLabel5")) self.file_menu.setTitle(_translate("MainWindow", "File")) self.visibility_menu.setTitle(_translate("MainWindow", "Visibility")) self.terrain_menu.setTitle("Terrain")
class Editor(QMainWindow): def __init__(self, taxfile=None, parent=None): super().__init__(parent) # Python => 3.0 method # super(Editor, self).__init__(parent) # Python < 3.0 method # load and set stylesheet look qtstyle_file = "modules/darkorange.stylesheet" with open(qtstyle_file, "r") as fh: self.mystyle = fh.read() self.setStyleSheet(self.mystyle) # Move whole window to the right self.move(710, 0) if (taxfile != None): self.taxyear = taxfile else: self.taxyear = "BCtax2018" self.initUI(self.taxyear) def openFile(self): fname, _filter = QFileDialog.getOpenFileName(self, 'Open json file', DATA_DIR, "Json file (*.json)") if (fname != ''): json_tax_file = fname.split("/")[-1:][0] self.updateTax(json_tax_file.split(".")[0]) def saveFile(self): data = self.readData() fname = "{}tax{}.json".format(data['info']['prov'], data['info']['year']) sname = DATA_DIR + "/{}".format(fname) if os.path.isfile(sname): msg_box = QMessageBox() msg_box.setStyleSheet(self.mystyle) button_reply = msg_box.question( self, 'File Exists', "Do you want overwrite {}?".format(fname), QMessageBox.Yes | QMessageBox.Cancel, QMessageBox.Cancel) if button_reply == QMessageBox.Yes: JsonFile(sname).save(data) if button_reply == QMessageBox.Cancel: print('Cancel') else: JsonFile(sname).save(data) def saveFileAs(self): data = self.readData() sname, _filter = QFileDialog.getSaveFileName(self, 'Save json File', DATA_DIR, "Json file (*.json)") if sname != '': JsonFile(sname).save(data) def updateTax(self, taxyear): self.taxyear = taxyear self.setWindowTitle("Editing {}".format(taxyear)) self.fillData(taxyear) def loadData(self, taxyear): taxdata = JsonFile("data/{}.json".format(taxyear)) return taxdata.load() def initMenu(self): self.menubar = QMenuBar() self.menubar.setGeometry(QtCore.QRect(0, 0, 916, 28)) self.menubar.setObjectName("menubar") self.menuFile = QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuFile.setTitle("File") self.setMenuBar(self.menubar) self.statusbar = QStatusBar() self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.actionOpen = QAction() self.actionOpen.setObjectName("actionOpen") self.actionOpen.triggered.connect(self.openFile) self.actionOpen.setText("Open") self.actionSave = QAction() self.actionSave.setObjectName("actionSave") self.actionSave.triggered.connect(self.saveFile) self.actionSave.setText("Save") self.actionSaveAs = QAction() self.actionSaveAs.setObjectName("actionSaveAs") self.actionSaveAs.triggered.connect(self.saveFileAs) self.actionSaveAs.setText("Save As..") self.actionExit = QAction(QtGui.QIcon('images/exit.png'), '&Exit', self) self.actionExit.setShortcut('Ctrl+Q') self.actionExit.setStatusTip('Exit application') self.actionExit.setObjectName("actionExit") self.actionExit.triggered.connect(qApp.quit) self.actionExit.setText("Exit") self.menuFile.addAction(self.actionOpen) self.menuFile.addAction(self.actionSave) self.menuFile.addAction(self.actionSaveAs) self.menuFile.addAction(self.actionExit) self.menubar.addAction(self.menuFile.menuAction()) def initUI(self, taxyear): self.setObjectName("MainWindow") self.setEnabled(True) self.resize(400, 800) self.centralwidget = QWidget() self.verticalLayout_3 = QVBoxLayout(self.centralwidget) self.splitter = QSplitter(self.centralwidget) # --------------------- TOP MENU ------------------------- self.initMenu() # ------------- Province ---------------- self.ProvinceLabel = QLabel(self.splitter) self.provinceBox = QComboBox(self.splitter) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.provinceBox.addItem("Alberta") self.provinceBox.setItemText(0, "AB") self.provinceBox.addItem("British Columbia") self.provinceBox.setItemText(1, "BC") self.provinceBox.addItem("Manitoba") self.provinceBox.setItemText(2, "MB") self.provinceBox.addItem("New Brunswick") self.provinceBox.setItemText(3, "NB") self.provinceBox.addItem("Newfoundland and Labrador") self.provinceBox.setItemText(4, "NL") self.provinceBox.addItem("Nova Scotia") self.provinceBox.setItemText(5, "NS") self.provinceBox.addItem("Nunavut") self.provinceBox.setItemText(6, "BC") self.provinceBox.addItem("Ontario") self.provinceBox.setItemText(7, "ON") self.provinceBox.addItem("Prince Edward Island") self.provinceBox.setItemText(8, "PE") self.provinceBox.addItem("Quebec") self.provinceBox.setItemText(9, "QC") self.provinceBox.addItem("Saskatchewan") self.provinceBox.setItemText(10, "SK") self.taxYearLabel = QLabel(self.splitter) self.taxYearBox = QSpinBox(self.splitter) self.taxYearBox.setMinimum(1990) self.taxYearBox.setMaximum(2050) self.taxYearBox.setValue(2018) self.verticalLayout_3.addWidget(self.splitter) self.tabWidget = QTabWidget(self.centralwidget) self.ProvincialTab = QWidget() self.verticalLayout = QVBoxLayout(self.ProvincialTab) self.provLabel = QLabel(self.ProvincialTab) self.verticalLayout.addWidget(self.provLabel) # ---------- PROVINCIAL TABLE --------------- self.provTable = QTableWidget(self.ProvincialTab) self.provTable.setColumnCount(3) self.provTable.setRowCount(6) font = QtGui.QFont() font.setPointSize(9) item = QTableWidgetItem() self.provTable.setHorizontalHeaderItem(0, item) self.provTable.horizontalHeaderItem(0).setText("Bracket From") self.provTable.horizontalHeaderItem(0).setFont(font) item = QTableWidgetItem() self.provTable.setHorizontalHeaderItem(1, item) self.provTable.horizontalHeaderItem(1).setText("Bracket To") self.provTable.horizontalHeaderItem(1).setFont(font) item = QTableWidgetItem() self.provTable.setHorizontalHeaderItem(2, item) self.provTable.horizontalHeaderItem(2).setText("tax Rate") self.provTable.horizontalHeaderItem(2).setFont(font) self.provTable.horizontalHeader().setDefaultSectionSize(110) self.provTable.horizontalHeader().setStretchLastSection(True) self.provTable.verticalHeader().setVisible(False) self.verticalLayout.addWidget(self.provTable) self.provPerLabel = QLabel(self.ProvincialTab) self.verticalLayout.addWidget(self.provPerLabel) # ----------- PROVINCE PERSONAL ------------------- self.provPerTable = QTableWidget(self.ProvincialTab) self.provPerTable.setMaximumSize(QtCore.QSize(16777215, 60)) self.provPerTable.setRowCount(1) self.provPerTable.setColumnCount(2) self.provPerTable.setObjectName("provPerTable") item = QTableWidgetItem() self.provPerTable.setVerticalHeaderItem(0, item) item = QTableWidgetItem() self.provPerTable.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.provPerTable.setHorizontalHeaderItem(1, item) self.provPerTable.horizontalHeader().setDefaultSectionSize(180) self.provPerTable.horizontalHeader().setStretchLastSection(True) self.provPerTable.verticalHeader().setVisible(False) self.provPerTable.verticalHeader().setStretchLastSection(True) self.verticalLayout.addWidget(self.provPerTable) self.tabWidget.addTab(self.ProvincialTab, "") self.FederalTab = QWidget() self.FederalTab.setObjectName("FederalTab") self.verticalLayout_2 = QVBoxLayout(self.FederalTab) self.verticalLayout_2.setObjectName("verticalLayout_2") self.fedLabel = QLabel(self.FederalTab) sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.fedLabel.sizePolicy().hasHeightForWidth()) self.fedLabel.setSizePolicy(sizePolicy) self.fedLabel.setAlignment(QtCore.Qt.AlignCenter) self.fedLabel.setObjectName("fedLabel") self.verticalLayout_2.addWidget(self.fedLabel) # ----------- FEDERAL TABLE ----------------- self.fedTable = QTableWidget(self.FederalTab) self.fedTable.setColumnCount(3) self.fedTable.setRowCount(5) font = QtGui.QFont() font.setPointSize(9) item = QTableWidgetItem() self.fedTable.setHorizontalHeaderItem(0, item) self.fedTable.horizontalHeaderItem(0).setText("Bracket From") self.fedTable.horizontalHeaderItem(0).setFont(font) item = QTableWidgetItem() self.fedTable.setHorizontalHeaderItem(1, item) self.fedTable.horizontalHeaderItem(1).setText("Bracket To") self.fedTable.horizontalHeaderItem(1).setFont(font) item = QTableWidgetItem() self.fedTable.setHorizontalHeaderItem(2, item) self.fedTable.horizontalHeaderItem(2).setText("tax Rate") self.fedTable.horizontalHeaderItem(2).setFont(font) self.fedTable.horizontalHeader().setDefaultSectionSize(100) self.fedTable.horizontalHeader().setStretchLastSection(True) self.fedTable.verticalHeader().setVisible(False) self.verticalLayout_2.addWidget(self.fedTable) self.fedPerLabel = QLabel(self.FederalTab) sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.fedPerLabel.sizePolicy().hasHeightForWidth()) self.fedPerLabel.setSizePolicy(sizePolicy) self.fedPerLabel.setAlignment(QtCore.Qt.AlignCenter) self.fedPerLabel.setObjectName("fedPerLabel") self.verticalLayout_2.addWidget(self.fedPerLabel) # ----------- FEDERAL PERSONAL TABLE ----------------- self.fedPerTable = QTableWidget(self.FederalTab) sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.fedPerTable.sizePolicy().hasHeightForWidth()) self.fedPerTable.setSizePolicy(sizePolicy) self.fedPerTable.setMaximumSize(QtCore.QSize(16777215, 60)) self.fedPerTable.setRowCount(1) self.fedPerTable.setColumnCount(2) self.fedPerTable.setObjectName("fedPerTable") item = QTableWidgetItem() self.fedPerTable.setVerticalHeaderItem(0, item) item = QTableWidgetItem() self.fedPerTable.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.fedPerTable.setHorizontalHeaderItem(1, item) self.fedPerTable.horizontalHeader().setDefaultSectionSize(180) self.fedPerTable.horizontalHeader().setStretchLastSection(True) self.fedPerTable.verticalHeader().setVisible(False) self.fedPerTable.verticalHeader().setStretchLastSection(True) self.verticalLayout_2.addWidget(self.fedPerTable) self.tabWidget.addTab(self.FederalTab, "") self.verticalLayout_3.addWidget(self.tabWidget) self.eiLabel = QLabel(self.centralwidget) self.eiLabel.setAlignment(QtCore.Qt.AlignCenter) self.eiLabel.setObjectName("eiLabel") self.verticalLayout_3.addWidget(self.eiLabel) self.eiTable = QTableWidget(self.centralwidget) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.eiTable.sizePolicy().hasHeightForWidth()) self.eiTable.setSizePolicy(sizePolicy) self.eiTable.setMaximumSize(QtCore.QSize(16777215, 60)) self.eiTable.setObjectName("eiTable") self.eiTable.setColumnCount(2) self.eiTable.setRowCount(1) item = QTableWidgetItem() self.eiTable.setVerticalHeaderItem(0, item) item = QTableWidgetItem() self.eiTable.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.eiTable.setHorizontalHeaderItem(1, item) self.eiTable.horizontalHeader().setDefaultSectionSize(180) self.eiTable.horizontalHeader().setStretchLastSection(True) self.eiTable.verticalHeader().setVisible(False) self.eiTable.verticalHeader().setStretchLastSection(True) self.verticalLayout_3.addWidget(self.eiTable) self.cppLabel = QLabel(self.centralwidget) self.cppLabel.setAlignment(QtCore.Qt.AlignCenter) self.cppLabel.setObjectName("cppLabel") self.cppLabel.setText("Canada Pension Plan") self.verticalLayout_3.addWidget(self.cppLabel) self.cppTable = QTableWidget(self.centralwidget) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.cppTable.sizePolicy().hasHeightForWidth()) self.cppTable.setSizePolicy(sizePolicy) self.cppTable.setMaximumSize(QtCore.QSize(16777215, 60)) self.cppTable.setObjectName("cppTable") self.cppTable.setColumnCount(3) self.cppTable.setRowCount(1) item = QTableWidgetItem() self.cppTable.setVerticalHeaderItem(0, item) item = QTableWidgetItem() self.cppTable.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.cppTable.setHorizontalHeaderItem(1, item) item = QTableWidgetItem() self.cppTable.setHorizontalHeaderItem(2, item) self.cppTable.horizontalHeader().setDefaultSectionSize(120) self.cppTable.horizontalHeader().setStretchLastSection(True) self.cppTable.verticalHeader().setVisible(False) self.cppTable.verticalHeader().setStretchLastSection(True) self.verticalLayout_3.addWidget(self.cppTable) self.setCentralWidget(self.centralwidget) item = self.cppTable.horizontalHeaderItem(0) item.setText("max contrib") item = self.cppTable.horizontalHeaderItem(1) item.setText("tax") item = self.cppTable.horizontalHeaderItem(2) item.setText("excempt") self.retranslateUi() self.tabWidget.setCurrentIndex(0) # QtCore.QMetaObject.connectSlotsByName() self.setWindowTitle("Editing {}".format(taxyear)) self.fillData(taxyear) def retranslateUi(self): _translate = QtCore.QCoreApplication.translate self.ProvinceLabel.setText(_translate("MainWindow", "Province")) self.taxYearLabel.setText(_translate("MainWindow", "Tax Year")) self.provLabel.setText( _translate("MainWindow", "Provincial Tax Rates, Personal income")) self.provPerLabel.setText(_translate("MainWindow", "Personal Amount")) item = self.provPerTable.verticalHeaderItem(0) item.setText(_translate("MainWindow", "1")) item = self.provPerTable.horizontalHeaderItem(0) item.setText(_translate("MainWindow", "amount")) item = self.provPerTable.horizontalHeaderItem(1) item.setText(_translate("MainWindow", "tax rate")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.ProvincialTab), _translate("MainWindow", "Provincial Tax")) self.fedLabel.setText(_translate("MainWindow", "Federal Tax Rates")) self.fedPerLabel.setText(_translate("MainWindow", "Personal Amount")) item = self.fedPerTable.verticalHeaderItem(0) item.setText(_translate("MainWindow", "1")) item = self.fedPerTable.horizontalHeaderItem(0) item.setText(_translate("MainWindow", "amount")) item = self.fedPerTable.horizontalHeaderItem(1) item.setText(_translate("MainWindow", "tax rate")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.FederalTab), _translate("MainWindow", "Federal Tax")) self.eiLabel.setText(_translate("MainWindow", "Employee Insurance")) item = self.eiTable.verticalHeaderItem(0) item.setText(_translate("MainWindow", "Employee Insurance")) item = self.eiTable.horizontalHeaderItem(0) item.setText(_translate("MainWindow", "maxei")) item = self.eiTable.horizontalHeaderItem(1) item.setText(_translate("MainWindow", "tax")) def readData(self): taxdata = {} taxdata['info'] = {} taxdata['info']['year'] = self.taxYearBox.value() taxdata['info']['prov'] = self.provinceBox.currentText() taxdata['province'] = {} for i in range(0, 6): taxdata['province']['brk{}'.format(i + 1)] = [ float(self.provTable.item(i, c).text()) for c in range(3) ] taxdata['province']['PersonalAmount'] = [ float(self.provPerTable.item(0, c).text()) for c in range(2) ] taxdata['federal'] = {} for i in range(0, 5): taxdata['federal']['brk{}'.format(i + 1)] = [ float(self.fedTable.item(i, c).text()) for c in range(3) ] taxdata['federal']['PersonalAmount'] = [ float(self.fedPerTable.item(0, c).text()) for c in range(2) ] taxdata['employeeInsurance'] = {} taxdata['employeeInsurance']['maxei'] = [ float(self.eiTable.item(0, c).text()) for c in range(2) ] taxdata['cpp'] = {} taxdata['cpp']['maxcppContrib'] = [ float(self.cppTable.item(0, c).text()) for c in range(2) ] taxdata['cpp']['cppExempt'] = float(self.cppTable.item(0, 2).text()) return taxdata def fillData(self, taxyear): taxdata = self.loadData(taxyear) year = taxdata['info']['year'] print(year) self.taxYearBox.setValue(year) prov = taxdata['info']['prov'] index = self.provinceBox.findText(prov, QtCore.Qt.MatchFixedString) if index >= 0: self.provinceBox.setCurrentIndex(index) self.prov_brk = [ taxdata['province']['brk{}'.format(x)] for x in range(1, 7) ] self.prov_PersonalAmount = taxdata['province']['PersonalAmount'] self.federal_brk = [ taxdata['federal']['brk{}'.format(x)] for x in range(1, 6) ] self.federal_PersonalAmount = taxdata['federal']['PersonalAmount'] self.maxei = taxdata['employeeInsurance']['maxei'] self.maxcppContrib = taxdata['cpp']['maxcppContrib'] self.cppExempt = taxdata['cpp']['cppExempt'] for c in range(0, self.provTable.columnCount()): for r in range(0, self.provTable.rowCount()): item = QTableWidgetItem() item.setData(QtCore.Qt.EditRole, self.prov_brk[r][c]) self.provTable.setItem(r, c, item) for i in range(0, self.provPerTable.columnCount()): item = QTableWidgetItem() item.setData(QtCore.Qt.EditRole, self.prov_PersonalAmount[i]) self.provPerTable.setItem(0, i, item) for c in range(0, self.fedTable.columnCount()): for r in range(0, self.fedTable.rowCount()): item = QTableWidgetItem() item.setData(QtCore.Qt.EditRole, self.federal_brk[r][c]) self.fedTable.setItem(r, c, item) for i in range(0, self.fedPerTable.columnCount()): item = QTableWidgetItem() item.setData(QtCore.Qt.EditRole, self.federal_PersonalAmount[i]) self.fedPerTable.setItem(0, i, item) for i in range(0, self.eiTable.columnCount()): item = QTableWidgetItem() item.setData(QtCore.Qt.EditRole, self.maxei[i]) self.eiTable.setItem(0, i, item) item = QTableWidgetItem() item.setData(QtCore.Qt.EditRole, self.maxcppContrib[0]) self.cppTable.setItem(0, 0, item) item = QTableWidgetItem() item.setData(QtCore.Qt.EditRole, self.maxcppContrib[1]) self.cppTable.setItem(0, 1, item) item = QTableWidgetItem() item.setData(QtCore.Qt.EditRole, self.cppExempt) self.cppTable.setItem(0, 2, item)
class MainWindow(QMainWindow): tableContents = [] tableColumnCount = 8 tableRowCount = 10 workerCount = config['worker_num'] # 线程数 workers = [] # 保存线程对象 q = Queue() wtime = [0, 0] bgColor = QColor(180, 200, 230, 40) progressVal = 0 taskVal = 0 def __init__(self): super(MainWindow, self).__init__() self.description = self.tr("""<b>Checker</b><br /><br /> Version: %s<br /> %s<br /><br /> Project: <a href=\"%s\">1dot75cm/repo-checker</a><br /> License: %s<br /> Author: <a href=\"mailto:%s\">%s</a>""") % (__version__, __descript__, __url__, __license__, __email__, __author__) self.tableHeaders = [self.tr("Name"), self.tr("URL"), self.tr("Branch"), self.tr("RPM date [commit]"), self.tr("Release date [commit]"), self.tr("Latest date [commit]"), self.tr("Status"), self.tr("Comment")] self.setupUi(self) def setupUi(self, MainWindow): """初始化主窗口""" MainWindow.setObjectName("MainWindow") MainWindow.setMinimumSize(QSize(910, 450)) MainWindow.setWindowTitle(self.tr("Checker")) MainWindow.setAnimated(True) self.centralwidget = QWidget(MainWindow) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.centralwidget.setSizePolicy(sizePolicy) self.verticalLayout = QVBoxLayout(self.centralwidget) self.verticalLayout.setContentsMargins(5, 5, 5, 5) self.tableWidget = QTableWidget(self.centralwidget) self.setupTable() self.verticalLayout.addWidget(self.tableWidget) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setContentsMargins(5, 5, 5, 5) self.addButton = QPushButton(self.centralwidget) self.addButton.setFixedSize(QSize(25, 25)) self.addButton.setText("+") self.horizontalLayout.addWidget(self.addButton) self.delButton = QPushButton(self.centralwidget) self.delButton.setFixedSize(QSize(25, 25)) self.delButton.setText("-") self.horizontalLayout.addWidget(self.delButton) self.upButton = QPushButton(self.centralwidget) self.upButton.setFixedSize(QSize(25, 25)) self.upButton.setText("↑") self.upButton.setObjectName("up") self.horizontalLayout.addWidget(self.upButton) self.downButton = QPushButton(self.centralwidget) self.downButton.setFixedSize(QSize(25, 25)) self.downButton.setText("↓") self.horizontalLayout.addWidget(self.downButton) spacerItem = QSpacerItem(40, 20, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.progressBar = QProgressBar(self.centralwidget) self.progressBar.hide() self.horizontalLayout.addWidget(self.progressBar) self.label = QLabel(self.centralwidget) self.horizontalLayout.addWidget(self.label) spacerItem = QSpacerItem(40, 20, QSizePolicy.Minimum, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.checkButton = QPushButton(self.centralwidget) self.checkButton.setText(self.tr("Check")) self.horizontalLayout.addWidget(self.checkButton) self.updateButton = QPushButton(self.centralwidget) self.updateButton.setText(self.tr("Update item")) self.horizontalLayout.addWidget(self.updateButton) self.editRuleButton = QPushButton(self.centralwidget) self.editRuleButton.setText(self.tr("Edit rule")) self.horizontalLayout.addWidget(self.editRuleButton) self.verticalLayout.addLayout(self.horizontalLayout) MainWindow.setCentralWidget(self.centralwidget) # 菜单 self.menubar = QMenuBar(MainWindow) self.menubar.setGeometry(QRect(0, 0, 780, 34)) MainWindow.setMenuBar(self.menubar) self.fileMenu = QMenu(self.menubar) self.fileMenu.setTitle(self.tr("File")) self.menubar.addAction(self.fileMenu.menuAction()) self.toolMenu = QMenu(self.menubar) self.toolMenu.setTitle(self.tr("Tool")) self.menubar.addAction(self.toolMenu.menuAction()) self.helpMenu = QMenu(self.menubar) self.helpMenu.setTitle(self.tr("Help")) self.menubar.addAction(self.helpMenu.menuAction()) self.statusbar = QStatusBar(MainWindow) MainWindow.setStatusBar(self.statusbar) # 菜单项 self.aboutAction = QAction(MainWindow) self.aboutAction.setText(self.tr("About")) self.aboutAction.setObjectName("about") self.aboutQtAction = QAction(MainWindow) self.aboutQtAction.setText(self.tr("About Qt")) self.aboutQtAction.setObjectName("about_qt") self.openAction = QAction(MainWindow) self.openAction.setText(self.tr("&Open")) self.openAction.setShortcut('Ctrl+O') self.openAction.setStatusTip(self.tr('Open a file')) self.openAction.setObjectName("open") self.openUrlAction = QAction(MainWindow) self.openUrlAction.setText(self.tr("Open &url")) self.openUrlAction.setShortcut('Ctrl+U') self.openUrlAction.setStatusTip(self.tr('Open a file with url')) self.saveAction = QAction(MainWindow) self.saveAction.setText(self.tr("&Save")) self.saveAction.setShortcut('Ctrl+S') self.saveAction.setStatusTip(self.tr('Save a file')) self.saveAction.setObjectName("save") self.saveAsAction = QAction(MainWindow) self.saveAsAction.setText(self.tr("Save As")) self.saveAsAction.setObjectName("save_as") self.closeAction = QAction(MainWindow) self.closeAction.setText(self.tr("&Close")) self.closeAction.setShortcut('Ctrl+W') self.closeAction.setStatusTip(self.tr('Close current page')) self.exitAction = QAction(MainWindow) self.exitAction.setText(self.tr("&Exit")) self.exitAction.setShortcut('Ctrl+Q') self.exitAction.setStatusTip(self.tr('Exit application')) self.settingAction = QAction(MainWindow) self.settingAction.setText(self.tr("&Settings")) self.settingAction.setShortcut('Ctrl+P') self.settingAction.setStatusTip(self.tr('Open settings dialog')) self.helpMenu.addAction(self.aboutAction) self.helpMenu.addAction(self.aboutQtAction) self.toolMenu.addAction(self.settingAction) self.fileMenu.addAction(self.openAction) self.fileMenu.addAction(self.openUrlAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.saveAction) self.fileMenu.addAction(self.saveAsAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.closeAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAction) # Signal & Slot self.addButton.clicked.connect(self.addRowSlot) self.delButton.clicked.connect(self.delRowSlot) self.upButton.clicked.connect(self.moveRowSlot) self.downButton.clicked.connect(self.moveRowSlot) self.checkButton.clicked.connect(self.checkUpdateSlot) self.updateButton.clicked.connect(self.updateTableItemSlot) self.editRuleButton.clicked.connect(self.editTableItemRuleSlot) self.settingAction.triggered.connect(self.showSettingDialogSlot) self.aboutAction.triggered.connect(self.showAboutDialogSlot) self.aboutQtAction.triggered.connect(self.showAboutDialogSlot) self.openAction.triggered.connect(self.showFileDialogSlot) self.openUrlAction.triggered.connect(self.showOpenUrlDialogSlot) self.saveAction.triggered.connect(self.showFileDialogSlot) self.saveAsAction.triggered.connect(self.showFileDialogSlot) self.closeAction.triggered.connect(self.tableWidget.clearContents) self.exitAction.triggered.connect(self.close) self.tableWidget.itemChanged.connect(self.itemChangedSlot) self.tableWidget.itemClicked.connect(self.itemClickedForOpenUrlSlot) def closeEvent(self, event): """关闭应用提示""" reply = QMessageBox.question(self, self.tr('Message'), self.tr("Are you sure to quit?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() # 接受关闭事件 else: event.ignore() # 拒绝关闭事件 def itemClickedForOpenUrlSlot(self, item): """Ctrl+left 打开链接""" # http://stackoverflow.com/questions/3100090/ if item.column() == 1 and item.text() and \ qApp.keyboardModifiers() == Qt.ControlModifier: QDesktopServices.openUrl(QUrl(item.text())) # open url def itemChangedSlot(self, item): # QTableWidgetItem """捕获itemChanged信号, 修改表项""" try: self.tableContents[item.row()].load(item.column(), item.text()) except IndexError: pass def moveRowSlot(self): """移动行""" try: sourceRow = self.tableWidget.currentRow() destRow = sourceRow-1 if self.sender().objectName() == "up" else sourceRow+1 if sourceRow != -1: sourceItems = self.getRow(sourceRow) destItems = self.getRow(destRow) self.setRow(destRow, sourceItems) self.setRow(sourceRow, destItems) self.tableWidget.selectRow(destRow) # 修改焦点 log.debug(self.tableContents) except AttributeError: if self.sender().objectName() == "up": QMessageBox.warning(self, self.tr("Warning"), self.tr("The row is to top.")) else: QMessageBox.warning(self, self.tr("Warning"), self.tr("The row is to bottom.")) def getRow(self, rowIndex): """获取行""" rowItems = [] for i in range(7): item = self.tableWidget.item(rowIndex, i) rowItems.append(item.text()) rowItems.append(self.tableContents[rowIndex].get_rules(ui=True)) return rowItems def setRow(self, rowIndex, rowItems): """设置行""" for n, i in enumerate(rowItems): if n == len(rowItems) - 1: self.tableContents[rowIndex].set_rules(i) else: item = self.tableWidget.item(rowIndex, n) item.setText(i) def addRowSlot(self): """添加行""" rowIndex = self.tableWidget.rowCount() self.tableWidget.setRowCount(rowIndex + 1) self.tableContents.append(Checker()) self.updateTableSlot(0) # 更新列表控件 log.debug(self.tableContents) def delRowSlot(self): """删除行""" # 焦点默认在第一行,要设置setFocusPolicy(Qt.NoFocus) rowIndex = self.tableWidget.currentRow() if rowIndex != -1: self.tableWidget.removeRow(rowIndex) self.tableContents.remove(self.tableContents[rowIndex]) log.debug(self.tableContents) else: QMessageBox.warning(self, self.tr("Warning"), self.tr("Please select a row.")) def loadData(self, data): """载入数据""" self.tableContents = [] # list.clear() Python 3 for i in data: self.tableContents.append(Checker(i)) def checkUpdateSlot(self): """执行更新检查""" self.wtime[0] = int(time.time()) # 计时 self.statusbar.showMessage(self.tr("checking...")) self.progressBar.setValue(0) self.progressBar.show() self.progressVal = 0 self.taskVal = 0 for t in range(self.workerCount): t = WorkThread(self.q) # 耗时任务需要用线程执行,再刷新进度条 t.triggered.connect(self.updateTableSlot) self.workers.append(t) t.start() # 执行工作线程 # 填充队列 for item in self.tableContents: self.q.put(item) def updateTableSlot(self, val): """线程通过该槽,刷新进度条,表格内容""" if val: self.taskVal += val self.progressVal = self.taskVal / len(self.tableContents) * 100 self.progressBar.setValue(self.progressVal) self.label.setText("%s/%s" % (self.taskVal, len(self.tableContents))) self.tableWidget.setRowCount(len(self.tableContents)) # 行数 for n, i in enumerate(self.tableContents): items = i.dump() for j in range(self.tableWidget.columnCount()): item = QTableWidgetItem(items[j]) if j in [0, 1]: item.setToolTip(item.text()) self.tableWidget.setItem(n, j, item) self.setStatusColor(n) self.setBackgroundColor(self.bgColor) if self.progressVal == 100: self.wtime[1] = int(time.time()) self.statusbar.showMessage(self.tr( "finished (work time %ds)") % (self.wtime[1] - self.wtime[0])) def updateTableItemSlot(self): """更新指定的 RPM 日期为 Release 日期""" rowIndex = self.tableWidget.currentRow() if rowIndex != -1: try: item = self.tableWidget.item(rowIndex, 4) self.tableWidget.item(rowIndex, 3).setText(item.text()) self.tableContents[rowIndex].load_meta(item.text()) except (IndexError, AttributeError): QMessageBox.warning(self, self.tr("Warning"), self.tr("The row is empty.")) else: QMessageBox.warning(self, self.tr("Warning"), self.tr("Please select a row.")) def editTableItemRuleSlot(self): """编辑列表项规则""" rowIndex = self.tableWidget.currentRow() if rowIndex != -1: try: # 父控件, 标题, 标签提示, 默认值, window flags rules, ok = QInputDialog.getMultiLineText(self, self.tr("Edit rule"), self.tr("XPath rule(format: \"[(time, commit), (time, commit)]\"):"), re.sub("\),|],|',", lambda x: "%s\n" % x.group(), str(self.tableContents[rowIndex].get_rules(ui=True)) )) if ok: self.tableContents[rowIndex].set_rules(rules) except (IndexError, UnboundLocalError): QMessageBox.warning(self, self.tr("Warning"), self.tr("The row is empty.")) else: QMessageBox.warning(self, self.tr("Warning"), self.tr("Please select a row.")) def showSettingDialogSlot(self): """显示设置对话框""" settingDialog = SettingDialog() settingDialog.exec_() def showAboutDialogSlot(self): """显示关于对话框""" if self.sender().objectName() == "about": QMessageBox.about(self, self.tr("Checker"), self.description) else: QMessageBox.aboutQt(self, self.tr("Checker")) def showOpenUrlDialogSlot(self): """通过 Url 打开文件""" url, _ = QInputDialog.getText(self, self.tr("Open url"), self.tr("Enter url:"), QLineEdit.Normal, "") try: resp = backend.get(url) self.loadData(resp.json()) self.updateTableSlot(0) # 更新列表控件 self.statusbar.showMessage(self.tr("open url successfully")) except Exception as e: QMessageBox.warning(self, self.tr("Error"), self.tr("Open url failed. See below:\n%s") % e) self.statusbar.showMessage(self.tr("open url failed")) def loadCsvFile(self, fname): """load csv file (old format)""" _data = [] with open(fname, 'r') as fp: content = csv.reader(fp) for row in content: if len(row) and row[0][0] != "#": _data.append(row) self.loadData(_data) def showFileDialogSlot(self): """打开/保存数据至文件""" if self.sender().objectName() == "open": fname = QFileDialog.getOpenFileName(self, self.tr("Open file"), os.getcwd()) fname = fname[0] if isinstance(fname, tuple) else fname # qt5 tuple, qt4 str if fname: try: with open(fname, 'r') as fp: self.loadData(json.load(fp)) except AttributeError as e: QMessageBox.warning(self, self.tr("Error"), self.tr("Open file failed. See below:\n%s") % e) except: # json.decoder.JSONDecodeError Python 3 try: # load csv file (old format) self.loadCsvFile(fname) except Exception as e: QMessageBox.warning(self, self.tr("Error"), self.tr("The file does not contain JSON or CSV. See below:\n%s") % e) self.updateTableSlot(0) # 更新列表控件 self.statusbar.showMessage(self.tr("open file successfully")) elif self.sender().objectName() in ["save", "save_as"]: fname = QFileDialog.getSaveFileName(self, self.tr("Save file"), os.getcwd()) fname = fname[0] if isinstance(fname, tuple) else fname # qt5 tuple, qt4 str if fname: try: with open(fname, 'w') as fp: json.dump([i.dump(mode="raw") for i in self.tableContents], fp, ensure_ascii=False) self.statusbar.showMessage(self.tr("saved successfully")) except AttributeError as e: QMessageBox.warning(self, self.tr("Error"), self.tr("Save file failed. See below:\n%s") % e) def setBackgroundColor(self, color): """修改背景色""" for i in range(self.tableWidget.rowCount()): if i % 2 != 0: for j in range(self.tableWidget.columnCount()): item = self.tableWidget.item(i, j) if item: item.setBackground(color) def setStatusColor(self, rowIndex): """修改状态文字颜色""" item = self.tableWidget.item(rowIndex, 6) if item.text() == "normal": item.setForeground(Qt.darkGreen) elif item.text() == "update": item.setForeground(Qt.darkRed) elif item.text() == "error": item.setForeground(Qt.darkYellow) elif item.text() == "none": item.setForeground(Qt.gray) def setupTable(self): """初始化列表""" self.tableWidget.setFocusPolicy(Qt.NoFocus) # 无焦点 self.tableWidget.setGridStyle(Qt.DashDotLine) # 线类型 self.tableWidget.setWordWrap(True) self.tableWidget.setCornerButtonEnabled(True) self.tableWidget.horizontalHeader().setVisible(True) # 显示表头 #self.tableWidget.horizontalHeader().setSortIndicatorShown(True) # 排序指示器 self.tableWidget.horizontalHeader().setStretchLastSection(True) # 扩展最后一列 self.tableWidget.setColumnCount(self.tableColumnCount) # 列数 self.tableWidget.setRowCount(self.tableRowCount) # 行数 # 行头 for i in range(self.tableRowCount): item = QTableWidgetItem("%s" % (i+1)) self.tableWidget.setVerticalHeaderItem(i, item) # 行号 # 列头 for i in range(self.tableColumnCount): item = QTableWidgetItem(self.tableHeaders[i]) # QIcon, str self.tableWidget.setHorizontalHeaderItem(i, item) # 初始化表头 for i in [3, 4, 5]: self.tableWidget.resizeColumnToContents(i) # 根据内容调整列宽 # 初始化项目 for i in range(self.tableRowCount): self.tableContents.append(Checker()) for j in range(self.tableColumnCount): item = QTableWidgetItem() self.tableWidget.setItem(i, j, item) self.setBackgroundColor(self.bgColor)
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.grid_size = GRID_SIZE #adjusting main window self.resize(TILES_WINDOW_WIDTH, TILES_WINDOW_HEIGHT) self.move(0, 0) self.setWindowTitle("Trainer") #initializing tiles self.addTiles(TILE_WIDTH, TILE_HEIGHT) #initializing menubar self.menubar = QMenuBar(self) #adding menu options self.grid_menu = QMenu(self.menubar) self.grid_menu.setTitle("Grid") self.model_menu = QMenu(self.menubar) self.model_menu.setTitle("Model") self.file_menu = QMenu(self.menubar) self.file_menu.setTitle("File") #adding file submenu options exit = QAction(self) exit.setText("Exit") exit.setShortcut('Alt+F4') exit.triggered.connect(self.exit) self.file_menu.addAction(exit) #adding grid submenu options g3 = QAction(self) g3.setText("3 X 3") g3.triggered.connect(self.toGrid3) g3.setShortcut("3") self.grid_menu.addAction(g3) g5 = QAction(self) g5.setText("5 X 5") g5.triggered.connect(self.toGrid5) g5.setShortcut("5") self.grid_menu.addAction(g5) g7 = QAction(self) g7.setText("7 X 7") g7.triggered.connect(self.toGrid7) g7.setShortcut("7") self.grid_menu.addAction(g7) g9 = QAction(self) g9.setText("9 X 9") g9.setShortcut("9") g9.triggered.connect(self.toGrid9) self.grid_menu.addAction(g9) #add model submenus re_train = QAction(self) re_train.setText("Retrain") re_train.setShortcut('Ctrl+R') re_train.triggered.connect(self.retrain) self.model_menu.addAction(re_train) #registering menus to menubar self.menubar.addAction(self.file_menu.menuAction()) self.menubar.addAction(self.model_menu.menuAction()) self.menubar.addAction(self.grid_menu.menuAction()) #registering menubar self.menubar.move(0, 0) self.menubar.setDefaultUp(False) self.setMenuBar(self.menubar) #initializing and registering statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) def retrain(self): print("retrain") # to be implemented def exit(self): QCoreApplication.instance().quit() def toGrid3(self): self.changeGridSize(3) def toGrid5(self): self.changeGridSize(5) def toGrid7(self): self.changeGridSize(7) def toGrid9(self): self.changeGridSize(9) def changeGridSize(self, size): #change grid size to new size self.grid_size = size #redraw frames to get new look self.drawFrames() def addTiles(self, tile_width, tile_height): # initializing and registering centeral widget self.centeral_widget = QWidget(self) self.setCentralWidget(self.centeral_widget) #initialize tiles self.tiles = [] #add tiles according to grid size for i in range(0, self.grid_size): self.tiles.append([]) for j in range(0, self.grid_size): tile = Tile(self.centeral_widget) tile.move(TILES_MARGIN_LEFT * (j + 1) + tile_width * j, TILES_MARGIN_TOP * (i + 1) + tile_height * i) tile.resize(tile_width, tile_height) self.tiles[i].append(tile) def drawFrames(self): #draw images in frames #initial width and height width = TILE_WIDTH height = TILE_HEIGHT if DYNAMIC_WINDOW_SCALING: #if dynamic scalling is available resize tiles # according to current window size window_width = self.centeral_widget.width() window_height = self.centeral_widget.height() (width, height) = reconfig_tile_geometery(window_width, window_height, self.grid_size) #add tile views for images self.addTiles(width, height) #read test image img = cv2.imread("fish.jpg") #resize test image img = cv2.resize(img, (width, height)) #set test image in all tiles for i in range(0, self.grid_size): for j in range(0, self.grid_size): if random.random() < 0.5: self.tiles[i][j].lable = 1 else: self.tiles[i][j].lable = 0 self.tiles[i][j].image = img self.tiles[i][j].drawImage() def resizeEvent(self, event): self.drawFrames()
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.lastyear = int(time.strftime('%Y', time.localtime(time.time()))) - 1 self.in_parameters = {u'datetime': str(self.lastyear) + u'年', u'target_area': u'绍兴市', u'density_cell': u'10', u'density_class': 10, u'day_cell': u'15', u'day_class': 10, u'out_type': u'tiff'} self.setupUi() def setupUi(self): self.setObjectName("MainWindow") self.setFixedSize(1040, 915) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) icon = QIcon() icon.addPixmap(QPixmap('./resource/weather-thunder.png'),QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.centralwidget = QWidget(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth()) self.centralwidget.setSizePolicy(sizePolicy) self.centralwidget.setObjectName("centralwidget") self.layoutWidget = QWidget(self.centralwidget) self.layoutWidget.setGeometry(QRect(32, 10, 979, 851)) self.layoutWidget.setObjectName("layoutWidget") self.verticalLayout_5 =QVBoxLayout(self.layoutWidget) self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) self.verticalLayout_5.setObjectName("verticalLayout_5") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") spacerItem = QSpacerItem(300, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.datetime_label = QLabel(self.layoutWidget) self.datetime_label.setObjectName("datetime_label") self.horizontalLayout.addWidget(self.datetime_label) self.datetime = QDateEdit(self.layoutWidget) self.datetime.setDateTime(QDateTime(QDate(self.lastyear, 1, 1), QTime(0, 0, 0))) self.datetime.setObjectName("datetime") self.horizontalLayout.addWidget(self.datetime) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.target_area_label = QLabel(self.layoutWidget) self.target_area_label.setObjectName("target_area_label") self.horizontalLayout.addWidget(self.target_area_label) self.target_area = QComboBox(self.layoutWidget) self.target_area.setObjectName("target_area") self.target_area.addItem("") self.target_area.addItem("") self.target_area.addItem("") self.target_area.addItem("") self.target_area.addItem("") self.target_area.addItem("") self.horizontalLayout.addWidget(self.target_area) spacerItem2 = QSpacerItem(300, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem2) self.verticalLayout_5.addLayout(self.horizontalLayout) self.tabWidget = QTabWidget(self.layoutWidget) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) self.tabWidget.setSizePolicy(sizePolicy) self.tabWidget.setObjectName("tabWidget") self.density_tab = QWidget() self.density_tab.setObjectName("density_tab") self.verticalLayout_3 =QVBoxLayout(self.density_tab) self.verticalLayout_3.setObjectName("verticalLayout_3") self.verticalLayout_2 =QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.density_cell_label = QLabel(self.density_tab) self.density_cell_label.setObjectName("density_cell_label") self.horizontalLayout_2.addWidget(self.density_cell_label) self.density_cell = QSpinBox(self.density_tab) self.density_cell.setProperty("value", 10) self.density_cell.setObjectName("density_cell") self.horizontalLayout_2.addWidget(self.density_cell) spacerItem3 = QSpacerItem(40, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem3) self.density_class_label = QLabel(self.density_tab) self.density_class_label.setObjectName("density_class_label") self.horizontalLayout_2.addWidget(self.density_class_label) self.density_class = QSpinBox(self.density_tab) self.density_class.setProperty("value", 10) self.density_class.setObjectName("density_class") self.horizontalLayout_2.addWidget(self.density_class) spacerItem4 = QSpacerItem(478, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem4) self.density_mxd = QPushButton(self.density_tab) self.density_mxd.setObjectName("density_mxd") self.horizontalLayout_2.addWidget(self.density_mxd) self.verticalLayout_2.addLayout(self.horizontalLayout_2) self.density_view = QGraphicsView(self.density_tab) self.density_view.setObjectName("density_view") self.verticalLayout_2.addWidget(self.density_view) self.verticalLayout_3.addLayout(self.verticalLayout_2) self.tabWidget.addTab(self.density_tab, "") self.day_tab = QWidget() self.day_tab.setObjectName("day_tab") self.verticalLayout_4 =QVBoxLayout(self.day_tab) self.verticalLayout_4.setObjectName("verticalLayout_4") self.verticalLayout =QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout_3 =QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.day_cell_label = QLabel(self.day_tab) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.day_cell_label.sizePolicy().hasHeightForWidth()) self.day_cell_label.setSizePolicy(sizePolicy) self.day_cell_label.setObjectName("day_cell_label") self.horizontalLayout_3.addWidget(self.day_cell_label) self.day_cell = QSpinBox(self.day_tab) self.day_cell.setProperty("value", 15) self.day_cell.setObjectName("day_cell") self.horizontalLayout_3.addWidget(self.day_cell) spacerItem5 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem5) self.day_class_label = QLabel(self.day_tab) self.day_class_label.setObjectName("day_class_label") self.horizontalLayout_3.addWidget(self.day_class_label) self.day_class = QSpinBox(self.day_tab) self.day_class.setProperty("value", 10) self.day_class.setObjectName("day_class") self.horizontalLayout_3.addWidget(self.day_class) spacerItem6 = QSpacerItem(478, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem6) self.day_mxd = QPushButton(self.day_tab) self.day_mxd.setObjectName("day_mxd") self.horizontalLayout_3.addWidget(self.day_mxd) self.verticalLayout.addLayout(self.horizontalLayout_3) self.day_view = QGraphicsView(self.day_tab) self.day_view.setObjectName("day_view") self.verticalLayout.addWidget(self.day_view) self.verticalLayout_4.addLayout(self.verticalLayout) self.tabWidget.addTab(self.day_tab, "") self.verticalLayout_5.addWidget(self.tabWidget) self.horizontalLayout_4 =QHBoxLayout() self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.progressBar = QProgressBar(self.layoutWidget) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.progressBar.sizePolicy().hasHeightForWidth()) self.progressBar.setSizePolicy(sizePolicy) self.progressBar.setProperty("value", 0) self.progressBar.setObjectName("progressBar") self.horizontalLayout_4.addWidget(self.progressBar) self.execute_button = QPushButton(self.layoutWidget) sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.execute_button.sizePolicy().hasHeightForWidth()) self.execute_button.setSizePolicy(sizePolicy) self.execute_button.setObjectName("execute_button") self.horizontalLayout_4.addWidget(self.execute_button) self.verticalLayout_5.addLayout(self.horizontalLayout_4) self.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 1040, 26)) self.menubar.setObjectName("menubar") self.file_menu = QMenu(self.menubar) self.file_menu.setObjectName("file_menu") self.help_menu = QMenu(self.menubar) self.help_menu.setObjectName("help_menu") self.setMenuBar(self.menubar) self.statusbar = QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.action_add_data = QAction(self) self.action_add_data.setObjectName("action_add_data") self.action_help = QAction(self) self.action_help.setObjectName("action_help") self.action_about = QAction(self) self.action_about.setObjectName("action_about") self.action_save_pic = QAction(self) self.action_save_pic.setObjectName("action_save_pic") self.file_menu.addAction(self.action_add_data) self.file_menu.addAction(self.action_save_pic) self.help_menu.addAction(self.action_help) self.help_menu.addAction(self.action_about) self.menubar.addAction(self.file_menu.menuAction()) self.menubar.addAction(self.help_menu.menuAction()) self.retranslateUi() self.tabWidget.setCurrentIndex(0) QMetaObject.connectSlotsByName(self) self.center() self.show() self.target_area.activated[str].connect(self.updateTargetArea) self.datetime.dateChanged.connect(self.updateDatetime) self.density_cell.valueChanged.connect(self.updateDensityCell) self.density_class.valueChanged.connect(self.updateDensityClass) self.day_cell.valueChanged.connect(self.updateDayCell) self.day_class.valueChanged.connect(self.updateDayClass) self.action_add_data.triggered.connect(self.addData) self.action_save_pic.triggered.connect(self.savePic) self.action_about.triggered.connect(self.showAbout) self.action_help.triggered.connect(self.showHelp) self.execute_button.clicked.connect(self.execute) self.density_mxd.clicked.connect(self.openMxdDensity) self.day_mxd.clicked.connect(self.openMxdDay) self.density_mxd.setDisabled(True) self.day_mxd.setDisabled(True) self.action_save_pic.setDisabled(True) def execute(self): dir = u"E:/Documents/工作/雷电公报/闪电定位原始文本数据/" + self.in_parameters[u'datetime'] if os.path.exists(dir): datafiles = os.listdir(dir) datafiles = map(lambda x:os.path.join(dir,x),datafiles) self.in_parameters[u'origin_data_path'] = datafiles if not self.in_parameters.has_key(u'origin_data_path'): message = u"请加载%s的数据" % self.in_parameters[u'datetime'] msgBox = QMessageBox() msgBox.setText(message) msgBox.setIcon(QMessageBox.Information) icon = QIcon() icon.addPixmap(QPixmap('./resource/weather-thunder.png'), QIcon.Normal, QIcon.Off) msgBox.setWindowIcon(icon) msgBox.setWindowTitle(" ") msgBox.exec_() return self.execute_button.setDisabled(True) self.execute_button.setText(u'正在制图中……') self.progressBar.setMaximum(0) self.progressBar.setMinimum(0) self.action_add_data.setDisabled(True) self.target_area.setDisabled(True) self.datetime.setDisabled(True) self.density_cell.setDisabled(True) self.density_class.setDisabled(True) self.day_cell.setDisabled(True) self.day_class.setDisabled(True) # for outfile in self.in_parameters[u'origin_data_path']: # infile = # try: # with open(infile, 'w+') as in_f: # for line in in_f: # line = line.replace(u":",":") # in_f.write(line) # except Exception,inst: # print infile self.process_thread = WorkThread() self.process_thread.trigger.connect(self.finished) self.process_thread.beginRun(self.in_parameters) def finished(self): #绘制闪电密度图 ##清除上一次的QGraphicsView对象,防止其记录上一次图片结果,影响显示效果 self.density_view.setAttribute(Qt.WA_DeleteOnClose) self.verticalLayout_2.removeWidget(self.density_view) size = self.density_view.size() self.density_view.close() self.density_view = QGraphicsView(self.density_tab) self.density_view.setObjectName("density_view") self.density_view.resize(size) self.verticalLayout_2.addWidget(self.density_view) densityPic = ''.join([cwd,u'/bulletinTemp/', self.in_parameters[u'datetime'],u'/',self.in_parameters[u'datetime'], self.in_parameters[u'target_area'],u'闪电密度空间分布.tif']) scene = QGraphicsScene() pixmap_density = QPixmap(densityPic) scene.addPixmap(pixmap_density) self.density_view.setScene(scene) scale = float(self.density_view.width()) / pixmap_density.width() self.density_view.scale(scale, scale) #绘制雷暴日图 self.day_view.setAttribute(Qt.WA_DeleteOnClose) self.verticalLayout.removeWidget(self.day_view) size = self.day_view.size() self.day_view.close() self.day_view = QGraphicsView(self.day_tab) self.day_view.setObjectName("day_view") self.day_view.resize(size) self.verticalLayout.addWidget(self.day_view) dayPic = ''.join([cwd,u'/bulletinTemp/', self.in_parameters[u'datetime'],u'/',self.in_parameters[u'datetime'], self.in_parameters[u'target_area'],u'地闪雷暴日空间分布.tif']) pixmap_day = QPixmap(dayPic) scene = QGraphicsScene() scene.addPixmap(pixmap_day) self.day_view.resize(self.density_view.width(),self.density_view.height()) self.day_view.setScene(scene) scale = float(self.day_view.width()) / pixmap_day.width() self.day_view.scale(scale, scale) #处理进度条和执行按钮状态 self.progressBar.setMinimum(0) self.progressBar.setMaximum(100) self.progressBar.setValue(100) self.progressBar.setFormat(u'完成!') self.execute_button.setDisabled(False) self.execute_button.setText(u'执行') #改变一些控件的状态 self.action_add_data.setDisabled(False) self.target_area.setDisabled(False) self.datetime.setDisabled(False) self.density_cell.setDisabled(False) self.density_class.setDisabled(False) self.day_cell.setDisabled(False) self.day_class.setDisabled(False) self.density_mxd.setDisabled(False) self.day_mxd.setDisabled(False) self.action_save_pic.setDisabled(False) def addData(self): fnames = QFileDialog.getOpenFileNames(self, u'请选择原始的电闪数据', u'E:/Documents/工作/雷电公报/闪电定位原始文本数据', 'Text files (*.txt);;All(*.*)') self.in_parameters[u'origin_data_path'] = fnames[0] def savePic(self): densityPic = ''.join([cwd,u'/bulletinTemp/',self.in_parameters[u'datetime'],u'/', self.in_parameters[u'target_area'],'.gdb',u'/',self.in_parameters[u'datetime'], self.in_parameters[u'target_area'],u'闪电密度空间分布.tif']) dayPic = ''.join([cwd,u'/bulletinTemp/',self.in_parameters[u'datetime'],u'/', self.in_parameters[u'target_area'],'.gdb',u'/',self.in_parameters[u'datetime'], self.in_parameters[u'target_area'],u'地闪雷暴日空间分布.tif']) directory = QFileDialog.getExistingDirectory(self,u'请选择图片保存位置', u'E:/Documents/工作/雷电公报', QFileDialog.ShowDirsOnly|QFileDialog.DontResolveSymlinks) dest_density = os.path.join(directory,os.path.basename(densityPic)) dest_day = os.path.join(directory,os.path.basename(dayPic)) if os.path.isfile(dest_day) or os.path.isfile(dest_density): message = u"文件已经存在!" msgBox = QMessageBox() msgBox.setText(message) msgBox.setIcon(QMessageBox.Information) icon = QIcon() icon.addPixmap(QPixmap("./resource/weather-thunder.png"), QIcon.Normal, QIcon.Off) msgBox.setWindowIcon(icon) msgBox.setWindowTitle(" ") msgBox.exec_() return move(dayPic,directory) move(densityPic,directory) def openMxdDay(self): program = u'C:/Program Files (x86)/ArcGIS/Desktop10.3/bin/ArcMap.exe' src_dir = ''.join([cwd,u'/data/LightningBulletin.gdb']) dest_dir = ''.join([cwd,u"/bulletinTemp/",self.in_parameters[u'datetime'], u"/" , self.in_parameters[u'target_area']]) src_file = ''.join([self.in_parameters[u'target_area'] , u"地闪雷暴日空间分布模板.mxd"]) copy(os.path.join(src_dir,src_file),dest_dir) arguments = [os.path.join(dest_dir,src_file)] self.process = QProcess(self) self.process.start(program,arguments) def openMxdDensity(self): program = u'C:/Program Files (x86)/ArcGIS/Desktop10.3/bin/ArcMap.exe' src_dir = ''.join([cwd,u'/data/LightningBulletin.gdb']) dest_dir = ''.join([cwd,u"/bulletinTemp/",self.in_parameters[u'datetime'], u"/" , self.in_parameters[u'target_area']]) src_file = ''.join([self.in_parameters[u'target_area'] ,u"闪电密度空间分布模板.mxd"]) copy(os.path.join(src_dir,src_file),dest_dir) arguments = [os.path.join(dest_dir,src_file)] self.process = QProcess(self) self.process.start(program,arguments) def showAbout(self): self.about = About_Dialog() def showHelp(self): program = u'C:/Windows/hh.exe' arguments = [''.join([cwd,'/help/help.CHM'])] self.process = QProcess(self) self.process.start(program,arguments) def updateTargetArea(self, area): self.in_parameters[u'target_area'] = area def updateDatetime(self, date): self.in_parameters[u'datetime'] = str(date.year()) + u'年' if self.in_parameters.has_key(u'origin_data_path'): self.in_parameters.__delitem__(u'origin_data_path') def updateDensityCell(self, cell): self.in_parameters[u'density_cell'] = str(cell) def updateDensityClass(self, nclass): self.in_parameters[u'density_class'] = nclass def updateDayCell(self, cell): self.in_parameters[u'day_cell'] = str(cell) def updateDayClass(self, nclass): self.in_parameters[u'day_class'] = nclass def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def retranslateUi(self): _translate = QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "绍兴防雷中心 雷电公报制图")) self.datetime_label.setText(_translate("MainWindow", "年份")) self.datetime.setDisplayFormat(_translate("MainWindow", "yyyy")) self.target_area_label.setText(_translate("MainWindow", "地区")) self.target_area.setItemText(0, _translate("MainWindow", "绍兴市")) self.target_area.setItemText(1, _translate("MainWindow", "柯桥区")) self.target_area.setItemText(2, _translate("MainWindow", "上虞区")) self.target_area.setItemText(3, _translate("MainWindow", "诸暨市")) self.target_area.setItemText(4, _translate("MainWindow", "嵊州市")) self.target_area.setItemText(5, _translate("MainWindow", "新昌县")) self.density_cell_label.setText(_translate("MainWindow", "插值网格大小")) self.density_class_label.setText(_translate("MainWindow", "制图分类数目")) self.density_mxd.setText(_translate("MainWindow", "ArcGIS文档")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.density_tab), _translate("MainWindow", "电闪密度")) self.day_cell_label.setText(_translate("MainWindow", "插值网格大小")) self.day_class_label.setText(_translate("MainWindow", "制图分类数目")) self.day_mxd.setText(_translate("MainWindow", "ArcGIS文档")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.day_tab), _translate("MainWindow", "雷暴日")) self.execute_button.setText(_translate("MainWindow", "执行")) self.file_menu.setTitle(_translate("MainWindow", "文件")) self.help_menu.setTitle(_translate("MainWindow", "帮助")) self.action_add_data.setText(_translate("MainWindow", "加载数据")) self.action_help.setText(_translate("MainWindow", "使用说明")) self.action_about.setText(_translate("MainWindow", "关于")) self.action_save_pic.setText(_translate("MainWindow", "图片另存为"))
def __initMenu(self): """ Setup the menu bar. """ menu = QMenuBar(self) menuStart = QMenu("Start", menu) menu.addAction(menuStart.menuAction()) _menu_opt(menuStart, "Load data", self._dlg_load_data, "Ctrl+O") _menu_opt(menuStart, "Save", self._save_chart, "Ctrl+S") _menu_opt(menuStart, "New Data", self._dlg_new_data, "Ctrl+N") _menu_opt(menuStart, "Reshape", self._dlg_reshape, "Ctrl+R") _menu_opt(menuStart, "Difference", self._start_diff, "Ctrl+D") _menu_opt(menuStart, "Delete All Data", self._delete_all_data, "Ctrl+X") # Graph menu menuGraph = QMenu("Graph", menu) menu.addAction(menuGraph.menuAction()) _menu_opt(menuGraph, "Colorbar", self._add_colorbar).setCheckable(True) menuGraph.addSeparator() ag_cm = QActionGroup(self) _menu_opt(menuGraph, "Colormap 'jet'", lambda: self.Graph.colormap('jet'), act_grp=ag_cm) _menu_opt(menuGraph, "Colormap 'gray'", lambda: self.Graph.colormap('gray'), act_grp=ag_cm) _menu_opt(menuGraph, "Colormap 'hot'", lambda: self.Graph.colormap('hot'), act_grp=ag_cm) _menu_opt(menuGraph, "Colormap 'bwr'", lambda: self.Graph.colormap('bwr'), act_grp=ag_cm) _menu_opt(menuGraph, "Colormap 'viridis'", lambda: self.Graph.colormap('viridis'), act_grp=ag_cm).setChecked(True) # Operations menu menuOpr = QMenu("Operations", menu) menu.addAction(menuOpr.menuAction()) ag_op = QActionGroup(self) _menu_opt(menuOpr, "None", lambda: self.Shape.set_operation('None'), act_grp=ag_op).setChecked(True) _menu_opt(menuOpr, "Min", lambda: self.Shape.set_operation('min'), act_grp=ag_op) _menu_opt(menuOpr, "Mean", lambda: self.Shape.set_operation('mean'), act_grp=ag_op) _menu_opt(menuOpr, "Median", lambda: self.Shape.set_operation('median'), act_grp=ag_op) _menu_opt(menuOpr, "Max", lambda: self.Shape.set_operation('max'), act_grp=ag_op) # Plot menu menuPlot = QMenu("Plot", menu) menu.addAction(menuPlot.menuAction()) ag_plt = QActionGroup(self) ag_plt.setExclusive(False) self.MMM = _menu_opt(menuPlot, "min-mean-max plot", lambda: self._checkboxes(0), act_grp=ag_plt) self.MMM.triggered.connect(self._draw_data) self.Plot2D = _menu_opt(menuPlot, "2D as plot", lambda: self._checkboxes(1), act_grp=ag_plt) self.Plot2D.triggered.connect(self._draw_data) self.PlotScat = _menu_opt(menuPlot, "2D as Scatter", lambda: self._checkboxes(2), act_grp=ag_plt) self.PlotScat.triggered.connect(self._draw_data) self.Plot3D = _menu_opt(menuPlot, "3D as RGB", self._draw_data, act_grp=ag_plt) self.PrintFlat = _menu_opt(menuPlot, "Print Values as text", self._draw_data, act_grp=ag_plt) menuPlot.addSeparator() _menu_opt(menuPlot, "Keep Slice on data change", self._set_fixate_view, act_grp=ag_plt) dm = _menu_opt(menuPlot, "Dark Window mode", self._set_dark_mode, act_grp=ag_plt) if self.config.getboolean('opt', 'darkmode'): dm.setChecked(True) self._set_dark_mode(True) self.setMenuBar(menu) # Add a context menu self.contextMenu = QMenu(self) _menu_opt(self.contextMenu, "Rename", self.datatree.rename_key) _menu_opt(self.contextMenu, "Reshape", self._dlg_reshape) self.combine_opt = _menu_opt(self.contextMenu, "Combine Dataset", self._dlg_combine) _menu_opt(self.contextMenu, "Delete Data", self._delete_data)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.setup_window() self.create_menubar() self.start_main_menu() def setup_window(self, width=900, height=650): self.setWindowTitle("Focus") self.resize(width, height) self.setStyleSheet("background-color:rgb(239,234,150)") self._set_icon() def _set_icon(self): icon = QIcon() icon.addFile('imgs/tree_app_icon.png', QSize(512, 512)) self.setWindowIcon(icon) def create_menubar(self): self.menubar = QMenuBar(self) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle("File") self.menuFile.setStyleSheet("background-color:rgb(192,228,82);") self.setMenuBar(self.menubar) self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.action_new_tree = QAction(self) self.action_new_tree.setText("New focus") self.action_new_tree.setShortcut("Ctrl+N") self.action_new_tree.triggered.connect(self.new_tree) self.action_forest = QAction(self) self.action_forest.setText("Forest") self.action_forest.setShortcut("Ctrl+F") self.action_forest.triggered.connect(self.forest) self.action_exit = QAction(self) self.action_exit.setText("Exit") self.action_exit.setShortcut("Esc") self.action_exit.triggered.connect(self.exit_app) self.menuFile.addAction(self.action_new_tree) self.menuFile.addAction(self.action_forest) self.menuFile.addSeparator() self.menuFile.addAction(self.action_exit) self.menubar.addAction(self.menuFile.menuAction()) def start_main_menu(self): self.main_menu = MainMenu(self) self.setCentralWidget(self.main_menu) self.main_menu.button_new_tree.clicked.connect(self.new_tree) self.main_menu.button_forest.clicked.connect(self.forest) self.main_menu.button_exit.clicked.connect(self.exit_app) self.show() def new_tree(self): self.tree = Tree(self) self.setCentralWidget(self.tree) def forest(self): print('Forest') def exit_app(self): self.close()
class GUI(QMainWindow): def __init__(self): super(GUI, self).__init__() self.title = "MudShark v0.1" self.setWindowTitle(self.title) self.defWidth = 800 self.defHeight = 600 # self.setGeometry(100, 100, self.defWidth, self.defHeight) self.resize(self.defWidth, self.defHeight) self.host = "None" self.port = "None" self.log_name = "None" self.log_num = 0 self.mode = "None" self.connected = False self.client = None self.recSize = 0 self.rpw = 0 self.numRecs = 0 self.init_actions() self.modeChangeSignal = ModeChange() self.initUI() def initUI(self): # central widget contains a widget containing a vertical layout, # and that widget contains the stacked widget self.centralWidget = QWidget(self) self.centerVLayoutWidget = QWidget(self.centralWidget) self.centerVLayoutWidget.setGeometry(QRect(0, 0, 800, 550)) self.centralWidLayout = QVBoxLayout(self.centerVLayoutWidget) self.centralWidLayout.setContentsMargins(0, 0, 0, 0) # stacked widget is contained inside centralWidLayout self.stackedWidget = QStackedWidget(self.centerVLayoutWidget) # this is where we instantiate the different views inside stackedWidget self.initialView = InitialView(self) self.stackedWidget.addWidget(self.initialView) self.stackedWidget.setCurrentWidget(self.initialView) self.centralWidLayout.addWidget(self.stackedWidget) self.setCentralWidget(self.centralWidget) self.init_menu() self.init_statusbar() self.init_toolbar() self.show() def updateMode(self, mode): self.mode = mode self.modeChangeSignal.modeChange.connect(self.update_view) self.modeChangeSignal.modeChange.emit() def update_view(self): if self.mode == "None": self.stackedWidget.setCurrentWidget(self.initialView) elif self.mode == "Program log": self.stackedWidget.setCurrentWidget(self.programLogView) elif self.mode == "Retrieve log": self.logDet = client.engage_log(self.client, self.log_num, 0) self.recSize = self.logDet.record_size self.rpw = self.logDet.records_per_window self.numRecs = (self.logDet.max_records / self.logDet.records_per_window) self.records = client.retrieve_records(self.client, self.logDet.records_per_window, self.logDet.max_records, self.logDet.record_size) client.disengage_log(self.client, self.log_num) self.stackedWidget.setCurrentWidget(self.retrieveLogView) def init_actions(self): # exit action self.exitAct = QAction(QIcon('icons/exit.png'), '&Exit', self) self.exitAct.setShortcut('Ctrl+Q') self.exitAct.setStatusTip('Exit application') self.exitAct.setText("Exit") self.exitAct.triggered.connect(qApp.quit) # connect action self.connectAct = QAction(QIcon('icons/connect.png'), 'Connect', self) self.connectAct.setShortcut('Alt+C') self.connectAct.setStatusTip('Connect to a Modbus Meter') self.connectAct.setText("Connect") self.connectAct.triggered.connect(self.connect_popup) # disconnect action self.disconnectAct = QAction(QIcon('icons/disconnect.png'), 'Disconnect', self) self.disconnectAct.setShortcut('Ctrl+D') self.disconnectAct.setText("Disconnect") self.disconnectAct.setStatusTip('Disconnect from current' ' connection') self.disconnectAct.triggered.connect(self.disconnect) # export as action self.exportAsAct = QAction('Export As..', self) self.exportAsAct.setShortcut('Ctrl+e') self.exportAsAct.setText('Export As..') # help action self.helpAct = QAction('Help', self) self.helpAct.setShortcut('Ctrl+h') self.helpAct.setText('Help') # about the author action self.aboutAuthAct = QAction('About the Author', self) self.aboutAuthAct.setText('About the Author') def connect_popup(self): self.ConnectionWindow = cw.ConnectWindow(self) self.ConnectionWindow.show() def disconnect(self): self.host = "None" self.port = "None" self.log_name = "None" self.connected = False self.updateMode("None") self.update_statusbar() if self.client is not None: self.client.close() def init_statusbar(self): self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusMessage = QLabel() statusString = ("Host: " + self.host + " | Port: " + self.port + " | Log: " + self.log_name + " | Mode: " + self.mode + " | Connected: " + str(self.connected)) self.statusMessage.setText(statusString) self.statusBar().addPermanentWidget(self.statusMessage) def update_statusbar(self): self.statusBar().removeWidget(self.statusMessage) statusString = ("Host: " + self.host + " | Port: " + self.port + " | Log: " + self.log_name + " | Mode: " + self.mode + " | Connected: " + str(self.connected)) self.statusMessage = QLabel() self.statusMessage.setText(statusString) self.statusBar().addPermanentWidget(self.statusMessage) def init_toolbar(self): self.toolbar = self.addToolBar("Toolbar") self.toolbar.addAction(self.connectAct) self.toolbar.addAction(self.disconnectAct) self.toolbar.addAction(self.exitAct) def init_menu(self): self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 800, 20)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle("File") self.menuAbout = QMenu(self.menubar) self.menuAbout.setTitle("About") self.setMenuBar(self.menubar) # File -> Connect self.menuFile.addAction(self.connectAct) # File -> Disconnect self.menuFile.addAction(self.disconnectAct) self.menuFile.addSeparator() # File -> Export As.. self.menuFile.addAction(self.exportAsAct) self.menuFile.addSeparator() # File -> Exit self.menuFile.addAction(self.exitAct) # About -> Help self.menuAbout.addAction(self.helpAct) # About -> About the Author self.menuAbout.addAction(self.aboutAuthAct) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuAbout.menuAction()) ################## # EVENT HANDLING # ################## def toggleMenu(self, state): if state: self.statusbar.show() else: self.statusbar.hide() def contextMenuEvent(self, event): cmenu = QMenu(self) quitAct = cmenu.addAction("Quit") action = cmenu.exec_(self.mapToGlobal(event.pos())) if action == quitAct: qApp.quit()
class Window(QWidget): def __init__(self): super().__init__() self.setWindowIcon(QtGui.QIcon("icon.png")) self.setWindowTitle("DDOS Detector") self.resize(800, 600) self.Componnent() self.show() def Componnent(self): self.label = QLabel(self) self.label.setGeometry(QtCore.QRect(10, 20, 91, 51)) font = QtGui.QFont() font.setPointSize(14) self.label.setFont(font) self.label.setObjectName("label") self.label_2 = QLabel(self) self.label_2.setGeometry(QtCore.QRect(10, 70, 91, 51)) font = QtGui.QFont() font.setPointSize(14) self.label_2.setFont(font) self.label_2.setObjectName("label_2") self.lineEdit = QLineEdit(self) self.lineEdit.setGeometry(QtCore.QRect(100, 30, 561, 32)) font = QtGui.QFont() font.setPointSize(12) self.lineEdit.setFont(font) self.lineEdit.setObjectName("lineEdit") self.btnBrowse = QPushButton(self) self.btnBrowse.setGeometry(QtCore.QRect(680, 30, 88, 34)) font = QtGui.QFont() font.setPointSize(14) self.btnBrowse.setFont(font) self.btnBrowse.setObjectName("btnBrowse") self.comboBox = QComboBox(self) self.comboBox.setGeometry(QtCore.QRect(100, 80, 271, 32)) self.comboBox.setObjectName("comboBox") self.label_3 = QLabel(self) self.label_3.setGeometry(QtCore.QRect(200, 140, 111, 51)) font = QtGui.QFont() font.setPointSize(14) self.label_3.setFont(font) self.label_3.setObjectName("label_3") self.image = QLabel(self) self.image.setGeometry(QtCore.QRect(300, 200, 256, 256)) self.image.setObjectName("image") self.btnReport = QPushButton(self) self.btnReport.setGeometry(QtCore.QRect(310, 510, 171, 34)) font = QtGui.QFont() font.setPointSize(14) self.btnReport.setFont(font) self.btnReport.setObjectName("btnReport") self.btnCalculation = QPushButton(self) self.btnCalculation.setGeometry(QtCore.QRect(510, 510, 231, 34)) font = QtGui.QFont() font.setPointSize(14) self.btnCalculation.setFont(font) self.btnCalculation.setObjectName("btnCalculation") self.btnScan = QPushButton(self) self.btnScan.setGeometry(QtCore.QRect(390, 80, 88, 34)) font = QtGui.QFont() font.setPointSize(14) self.btnScan.setFont(font) self.btnScan.setObjectName("btnScan") self.result = QLabel(self) self.result.setGeometry(QtCore.QRect(330, 140, 400, 51)) font = QtGui.QFont() font.setPointSize(14) self.result.setFont(font) self.result.setObjectName("result") self.menubar = QMenuBar(self) self.menubar.setGeometry(QtCore.QRect(0, 0, 801, 30)) self.menubar.setObjectName("menubar") self.menuFile = QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuHelp = QMenu(self.menubar) self.menuHelp.setObjectName("menuHelp") self.actionOpen = QAction(self) self.actionOpen.setObjectName("actionOpen") self.actionExit = QAction(self) self.actionExit.setObjectName("actionExit") self.actionAbout = QAction(self) self.actionAbout.setObjectName("actionAbout") self.actionUsage = QAction(self) self.actionUsage.setObjectName("actionUsage") self.menuFile.addAction(self.actionOpen) self.menuFile.addAction(self.actionExit) self.menuHelp.addAction(self.actionAbout) self.menuHelp.addAction(self.actionUsage) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) self.label.setText("Filename") self.label_2.setText("Server IP") self.btnBrowse.setText("Browse") self.label_3.setText("Scan Result") self.image.setText("") self.btnReport.setText("View Scan Report") self.btnCalculation.setText("View Calculation Report") self.btnScan.setText("SCAN") self.btnScan.setDisabled(True) self.result.setText("Load file first") self.menuFile.setTitle("File") self.menuHelp.setTitle("Help") self.actionOpen.setText("Open") self.actionOpen.setShortcut("Ctrl+O") self.actionExit.setText("Exit") self.actionExit.setShortcut("Alt+F4") self.actionAbout.setText("About") self.actionAbout.setShortcut("Ctrl+A") self.actionUsage.setText("Usage") self.actionUsage.setShortcut("Ctrl+U") self.comboBox.setDisabled(True) self.btnBrowse.clicked.connect(self.openFile) self.actionOpen.triggered.connect(self.openFile) self.actionExit.triggered.connect(self.closeApp) self.btnScan.clicked.connect(self.scan) self.btnReport.clicked.connect(self.view_scan_report) self.btnCalculation.clicked.connect(self.view_calc_report) def openFile(self): fname = QFileDialog.getOpenFileName(self, 'Open file', "", "CSV Files (*.csv)") if fname != ('', ''): self.filePath = fname[0] self.lineEdit.setText(self.filePath) self.df = load_csv(self.filePath) self.result.setText("Set Server IP then SCAN") self.comboBox.setDisabled(False) self.btnScan.setDisabled(False) self.fetchServer() def fetchServer(self): server = self.df.Destination.unique() self.comboBox.clear() self.comboBox.addItems(server) self.selectionchange(0) self.comboBox.currentIndexChanged.connect(self.selectionchange) def selectionchange(self, i): self.server_ip = self.comboBox.currentText() def scan(self): self.df = filter_server(self.df, self.server_ip) check = QPixmap('res/check.png') cross = QPixmap('res/cross.png') report_dict, keanggotaan_length, keanggotaan_source, keanggotaan_packet, rule_dict, Z, Z_class, klasifikasi = calculate( self.df) if klasifikasi == 'POD': self.image.setPixmap(cross) self.result.setText( "<font color='red'>DDOS PING OF DEATH DETECTED!!!</font>") else: self.image.setPixmap(check) self.result.setText( "<font color='green'>DDOS PING OF DEATH NOT DETECTED!!!</font>" ) generate_report(report_dict, self.filePath, self.server_ip, klasifikasi) generate_calculation(report_dict, keanggotaan_length, keanggotaan_source, keanggotaan_packet, rule_dict, self.filePath, self.server_ip, klasifikasi) def view_scan_report(self): path = self.filePath.split('/')[-1] output = path.split('.')[0] + '-scan.html' output_path = self.filePath.strip(path) + output webbrowser.open(output_path, new=2) def view_calc_report(self): path = self.filePath.split('/')[-1] output = path.split('.')[0] + '-calculation.html' output_path = self.filePath.strip(path) + output webbrowser.open(output_path, new=2) def closeApp(self): sys.exit()
class MainWindow(QMainWindow): def __init__(self, app): QMainWindow.__init__(self, None) self.documentPath = None self.doc = DocumentModel(app=app.model) self.app = app self._setupUi() # Create base elements self.model = MainWindowModel(document=self.doc) self.model2view = {} self.alookup = Lookup(self, model=self.model.account_lookup) self.clookup = Lookup(self, model=self.model.completion_lookup) self.drsel = DateRangeSelector(mainwindow=self, view=self.dateRangeSelectorView) self.sfield = SearchField(model=self.model.search_field, view=self.searchLineEdit) self.recentDocuments = Recent(self.app, 'recentDocuments') self.recentDocuments.addMenu(self.menuOpenRecent) self.doc.view = self self.model.view = self self._updateUndoActions() self._bindSignals() def _setupUi(self): # has to take place *before* base elements creation self.setWindowTitle("moneyGuru") self.resize(700, 580) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) self.verticalLayout.setSpacing(0) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.topBar = QWidget(self.centralwidget) self.horizontalLayout_2 = QHBoxLayout(self.topBar) self.horizontalLayout_2.setContentsMargins(2, 0, 2, 0) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem) self.dateRangeSelectorView = DateRangeSelectorView(self.topBar) self.dateRangeSelectorView.setMinimumSize(QSize(220, 0)) self.horizontalLayout_2.addWidget(self.dateRangeSelectorView) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem1) self.searchLineEdit = SearchEdit(self.topBar) self.searchLineEdit.setMaximumSize(QSize(240, 16777215)) self.horizontalLayout_2.addWidget(self.searchLineEdit) self.verticalLayout.addWidget(self.topBar) self.tabBar = TabBarPlus(self.centralwidget) self.tabBar.setMinimumSize(QSize(0, 20)) self.verticalLayout.addWidget(self.tabBar) self.mainView = QStackedWidget(self.centralwidget) self.verticalLayout.addWidget(self.mainView) # Bottom buttons & status label self.bottomBar = QWidget(self.centralwidget) self.horizontalLayout = QHBoxLayout(self.bottomBar) self.horizontalLayout.setContentsMargins(2, 2, 2, 2) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) self.newItemButton = QPushButton(self.bottomBar) buttonSizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) buttonSizePolicy.setHorizontalStretch(0) buttonSizePolicy.setVerticalStretch(0) buttonSizePolicy.setHeightForWidth(self.newItemButton.sizePolicy().hasHeightForWidth()) self.newItemButton.setSizePolicy(buttonSizePolicy) self.newItemButton.setIcon(QIcon(QPixmap(':/plus_8'))) self.horizontalLayout.addWidget(self.newItemButton) self.deleteItemButton = QPushButton(self.bottomBar) self.deleteItemButton.setSizePolicy(buttonSizePolicy) self.deleteItemButton.setIcon(QIcon(QPixmap(':/minus_8'))) self.horizontalLayout.addWidget(self.deleteItemButton) self.editItemButton = QPushButton(self.bottomBar) self.editItemButton.setSizePolicy(buttonSizePolicy) self.editItemButton.setIcon(QIcon(QPixmap(':/info_gray_12'))) self.horizontalLayout.addWidget(self.editItemButton) self.horizontalLayout.addItem(horizontalSpacer(size=20)) self.graphVisibilityButton = QPushButton() self.graphVisibilityButton.setSizePolicy(buttonSizePolicy) self.graphVisibilityButton.setIcon(QIcon(QPixmap(':/graph_visibility_on_16'))) self.horizontalLayout.addWidget(self.graphVisibilityButton) self.piechartVisibilityButton = QPushButton() self.piechartVisibilityButton.setSizePolicy(buttonSizePolicy) self.piechartVisibilityButton.setIcon(QIcon(QPixmap(':/piechart_visibility_on_16'))) self.horizontalLayout.addWidget(self.piechartVisibilityButton) self.columnsVisibilityButton = QPushButton() self.columnsVisibilityButton.setSizePolicy(buttonSizePolicy) self.columnsVisibilityButton.setIcon(QIcon(QPixmap(':/columns_16'))) self.horizontalLayout.addWidget(self.columnsVisibilityButton) self.statusLabel = QLabel(tr("Status")) self.statusLabel.setAlignment(Qt.AlignCenter) self.horizontalLayout.addWidget(self.statusLabel) self.verticalLayout.addWidget(self.bottomBar) self.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 700, 20)) self.menuFile = QMenu(tr("File")) self.menuOpenRecent = QMenu(tr("Open Recent")) self.menuView = QMenu(tr("View")) self.menuDateRange = QMenu(tr("Date Range")) self.menuEdit = QMenu(tr("Edit")) self.menuHelp = QMenu(tr("Help")) self.setMenuBar(self.menubar) self.actionOpenDocument = QAction(tr("Open..."), self) self.actionOpenDocument.setShortcut("Ctrl+O") self.actionShowNetWorth = QAction(tr("Net Worth"), self) self.actionShowNetWorth.setShortcut("Ctrl+1") self.actionShowNetWorth.setIcon(QIcon(QPixmap(':/balance_sheet_48'))) self.actionShowProfitLoss = QAction(escapeamp(tr("Profit & Loss")), self) self.actionShowProfitLoss.setShortcut("Ctrl+2") self.actionShowProfitLoss.setIcon(QIcon(QPixmap(':/income_statement_48'))) self.actionShowTransactions = QAction(tr("Transactions"), self) self.actionShowTransactions.setShortcut("Ctrl+3") self.actionShowTransactions.setIcon(QIcon(QPixmap(':/transaction_table_48'))) self.actionShowSelectedAccount = QAction(tr("Show Account"), self) self.actionShowSelectedAccount.setShortcut("Ctrl+]") self.actionNewItem = QAction(tr("New Item"), self) self.actionNewItem.setShortcut("Ctrl+N") self.actionDeleteItem = QAction(tr("Remove Selected"), self) self.actionEditItem = QAction(tr("Show Info"), self) self.actionEditItem.setShortcut("Ctrl+I") self.actionToggleGraph = QAction(tr("Toggle Graph"), self) self.actionToggleGraph.setShortcut("Ctrl+Alt+G") self.actionTogglePieChart = QAction(tr("Toggle Pie Chart"), self) self.actionTogglePieChart.setShortcut("Ctrl+Alt+P") self.actionMoveUp = QAction(tr("Move Up"), self) self.actionMoveUp.setShortcut("Ctrl++") self.actionMoveDown = QAction(tr("Move Down"), self) self.actionMoveDown.setShortcut("Ctrl+-") self.actionNavigateBack = QAction(tr("Go Back"), self) self.actionNavigateBack.setShortcut("Ctrl+[") self.actionNewAccountGroup = QAction(tr("New Account Group"), self) self.actionNewAccountGroup.setShortcut("Ctrl+Shift+N") self.actionShowNextView = QAction(tr("Next View"), self) self.actionShowNextView.setShortcut("Ctrl+Shift+]") self.actionShowPreviousView = QAction(tr("Previous View"), self) self.actionShowPreviousView.setShortcut("Ctrl+Shift+[") self.actionNewDocument = QAction(tr("New Document"), self) self.actionImport = QAction(tr("Import..."), self) self.actionImport.setShortcut("Ctrl+Alt+I") self.actionExport = QAction(tr("Export..."), self) self.actionExport.setShortcut("Ctrl+Alt+E") self.actionSave = QAction(tr("Save"), self) self.actionSave.setShortcut("Ctrl+S") self.actionSaveAs = QAction(tr("Save As..."), self) self.actionSaveAs.setShortcut("Ctrl+Shift+S") self.actionAbout = QAction(tr("About moneyGuru"), self) self.actionToggleReconciliationMode = QAction(tr("Toggle Reconciliation Mode"), self) self.actionToggleReconciliationMode.setShortcut("Ctrl+Shift+R") self.actionToggleAccountExclusion = QAction(tr("Toggle Exclusion Status of Account"), self) self.actionToggleAccountExclusion.setShortcut("Ctrl+Shift+X") self.actionShowSchedules = QAction(tr("Schedules"), self) self.actionShowSchedules.setShortcut("Ctrl+4") self.actionShowSchedules.setIcon(QIcon(QPixmap(':/schedules_48'))) self.actionReconcileSelected = QAction(tr("Reconcile Selection"), self) self.actionReconcileSelected.setShortcut("Ctrl+R") self.actionMakeScheduleFromSelected = QAction(tr("Make Schedule from Selected"), self) self.actionMakeScheduleFromSelected.setShortcut("Ctrl+M") self.actionShowPreferences = QAction(tr("Preferences..."), self) self.actionPrint = QAction(tr("Print..."), self) self.actionPrint.setShortcut("Ctrl+P") self.actionQuit = QAction(tr("Quit moneyGuru"), self) self.actionQuit.setShortcut("Ctrl+Q") self.actionUndo = QAction(tr("Undo"), self) self.actionUndo.setShortcut("Ctrl+Z") self.actionRedo = QAction(tr("Redo"), self) self.actionRedo.setShortcut("Ctrl+Y") self.actionShowHelp = QAction(tr("moneyGuru Help"), self) self.actionShowHelp.setShortcut("F1") self.actionDuplicateTransaction = QAction(tr("Duplicate Transaction"), self) self.actionDuplicateTransaction.setShortcut("Ctrl+D") self.actionJumpToAccount = QAction(tr("Jump to Account..."), self) self.actionJumpToAccount.setShortcut("Ctrl+Shift+A") self.actionNewTab = QAction(tr("New Tab"), self) self.actionNewTab.setShortcut("Ctrl+T") self.actionCloseTab = QAction(tr("Close Tab"), self) self.actionCloseTab.setShortcut("Ctrl+W") self.menuFile.addAction(self.actionNewDocument) self.menuFile.addAction(self.actionNewTab) self.menuFile.addAction(self.actionOpenDocument) self.menuFile.addAction(self.menuOpenRecent.menuAction()) self.menuFile.addAction(self.actionImport) self.menuFile.addSeparator() self.menuFile.addAction(self.actionCloseTab) self.menuFile.addAction(self.actionSave) self.menuFile.addAction(self.actionSaveAs) self.menuFile.addAction(self.actionExport) self.menuFile.addAction(self.actionPrint) self.menuFile.addAction(self.actionQuit) self.menuView.addAction(self.actionShowNetWorth) self.menuView.addAction(self.actionShowProfitLoss) self.menuView.addAction(self.actionShowTransactions) self.menuView.addAction(self.actionShowSchedules) self.menuView.addAction(self.actionShowPreviousView) self.menuView.addAction(self.actionShowNextView) self.menuView.addAction(self.menuDateRange.menuAction()) self.menuView.addAction(self.actionShowPreferences) self.menuView.addAction(self.actionToggleGraph) self.menuView.addAction(self.actionTogglePieChart) self.menuEdit.addAction(self.actionNewItem) self.menuEdit.addAction(self.actionNewAccountGroup) self.menuEdit.addAction(self.actionDeleteItem) self.menuEdit.addAction(self.actionEditItem) self.menuEdit.addSeparator() self.menuEdit.addAction(self.actionMoveUp) self.menuEdit.addAction(self.actionMoveDown) self.menuEdit.addAction(self.actionDuplicateTransaction) self.menuEdit.addAction(self.actionMakeScheduleFromSelected) self.menuEdit.addAction(self.actionReconcileSelected) self.menuEdit.addAction(self.actionToggleReconciliationMode) self.menuEdit.addAction(self.actionToggleAccountExclusion) self.menuEdit.addSeparator() self.menuEdit.addAction(self.actionShowSelectedAccount) self.menuEdit.addAction(self.actionNavigateBack) self.menuEdit.addAction(self.actionJumpToAccount) self.menuEdit.addSeparator() self.menuEdit.addAction(self.actionUndo) self.menuEdit.addAction(self.actionRedo) self.menuHelp.addAction(self.actionShowHelp) self.menuHelp.addAction(self.actionAbout) mainmenus = [self.menuFile, self.menuEdit, self.menuView, self.menuHelp] for menu in mainmenus: self.menubar.addAction(menu.menuAction()) setAccelKeys(menu) setAccelKeys(self.menubar) self.tabBar.setMovable(True) self.tabBar.setTabsClosable(True) self.tabBar.setExpanding(False) seq = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Right) self._shortcutNextTab = QShortcut(seq, self) seq = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Left) self._shortcutPrevTab = QShortcut(seq, self) def _bindSignals(self): self.newItemButton.clicked.connect(self.actionNewItem.trigger) self.deleteItemButton.clicked.connect(self.actionDeleteItem.trigger) self.editItemButton.clicked.connect(self.actionEditItem.trigger) self.graphVisibilityButton.clicked.connect(self.actionToggleGraph.trigger) self.piechartVisibilityButton.clicked.connect(self.actionTogglePieChart.trigger) self.columnsVisibilityButton.clicked.connect(self.columnsVisibilityButtonClicked) self.recentDocuments.mustOpenItem.connect(self.open) self.tabBar.currentChanged.connect(self.currentTabChanged) self.tabBar.tabCloseRequested.connect(self.tabCloseRequested) self.tabBar.tabMoved.connect(self.tabMoved) self.tabBar.plusClicked.connect(self.model.new_tab) # Views self.actionShowNetWorth.triggered.connect(self.showNetWorthTriggered) self.actionShowProfitLoss.triggered.connect(self.showProfitLossTriggered) self.actionShowTransactions.triggered.connect(self.showTransactionsTriggered) self.actionShowSchedules.triggered.connect(self.showSchedulesTriggered) self.actionShowPreviousView.triggered.connect(self.showPreviousViewTriggered) self.actionShowNextView.triggered.connect(self.showNextViewTriggered) self.actionShowPreferences.triggered.connect(self.app.showPreferences) self.actionToggleGraph.triggered.connect(self.toggleGraphTriggered) self.actionTogglePieChart.triggered.connect(self.togglePieChartTriggered) # Document Edition self.actionNewItem.triggered.connect(self.newItemTriggered) self.actionNewAccountGroup.triggered.connect(self.newAccountGroupTriggered) self.actionDeleteItem.triggered.connect(self.deleteItemTriggered) self.actionEditItem.triggered.connect(self.editItemTriggered) self.actionMoveUp.triggered.connect(self.moveUpTriggered) self.actionMoveDown.triggered.connect(self.moveDownTriggered) self.actionDuplicateTransaction.triggered.connect(self.model.duplicate_item) self.actionUndo.triggered.connect(self.model.undo) self.actionRedo.triggered.connect(self.model.redo) # Open / Save / Import / Export / New self.actionNewDocument.triggered.connect(self.new) self.actionOpenDocument.triggered.connect(self.openDocument) self.actionImport.triggered.connect(self.importDocument) self.actionSave.triggered.connect(self.save) self.actionSaveAs.triggered.connect(self.saveAs) self.actionExport.triggered.connect(self.model.export) # Misc self.actionNewTab.triggered.connect(self.model.new_tab) self.actionCloseTab.triggered.connect(self.closeTabTriggered) self.actionShowSelectedAccount.triggered.connect(self.model.show_account) self.actionNavigateBack.triggered.connect(self.navigateBackTriggered) self.actionJumpToAccount.triggered.connect(self.jumpToAccountTriggered) self.actionMakeScheduleFromSelected.triggered.connect(self.makeScheduleFromSelectedTriggered) self.actionReconcileSelected.triggered.connect(self.reconcileSelectedTriggered) self.actionToggleReconciliationMode.triggered.connect(self.toggleReconciliationModeTriggered) self.actionToggleAccountExclusion.triggered.connect(self.toggleAccountExclusionTriggered) self.actionPrint.triggered.connect(self._print) self.actionShowHelp.triggered.connect(self.app.showHelp) self.actionAbout.triggered.connect(self.aboutTriggered) self.actionQuit.triggered.connect(self.close) # Extra Shortcuts self._shortcutNextTab.activated.connect(self.showNextViewTriggered) self._shortcutPrevTab.activated.connect(self.showPreviousViewTriggered) # --- QWidget overrides def closeEvent(self, event): if self.confirmDestructiveAction(): event.accept() else: event.ignore() # --- Private def _print(self): dialog = QPrintDialog(self) if dialog.exec_() != QPrintDialog.Accepted: return printer = dialog.printer() currentView = self.mainView.currentWidget() viewPrinter = ViewPrinter(printer, currentView) currentView.fitViewsForPrint(viewPrinter) viewPrinter.render() def _getViewforPane(self, pane_type, pane_view): if pane_view in self.model2view: view = self.model2view[pane_view] else: view = PANETYPE2VIEWCLASS[pane_type](model=pane_view, mainwindow=self) self.model2view[pane_view] = view self.mainView.addWidget(view) view.restoreSubviewsSize() return view def _setTabIndex(self, index): if not self.tabBar.count(): return self.tabBar.setCurrentIndex(index) self._updateActionsState() pane_type = self.model.pane_type(index) pane_view = self.model.pane_view(index) view = self._getViewforPane(pane_type, pane_view) self.mainView.setCurrentWidget(view) view.setFocus() def _activeView(self): paneIndex = self.model.current_pane_index return self.model.pane_view(paneIndex) def _updateActionsState(self): # Updates enable/disable checked/unchecked state of all actions. These state can change # under various conditions: main view change, date range type change and when reconciliation # mode is toggled # Determine what actions are enabled view = self._activeView() viewType = view.VIEW_TYPE isSheet = viewType in {PaneType.NetWorth, PaneType.Profit} isTransactionOrEntryTable = viewType in {PaneType.Transaction, PaneType.Account} canToggleReconciliation = viewType == PaneType.Account and view.can_toggle_reconciliation_mode newItemLabel = { PaneType.NetWorth: tr("New Account"), PaneType.Profit: tr("New Account"), PaneType.Transaction: tr("New Transaction"), PaneType.Account: tr("New Transaction"), PaneType.Schedule: tr("New Schedule"), PaneType.GeneralLedger: tr("New Transaction"), }.get(viewType, tr("New Item")) # XXX make "New Item" disabled self.actionNewItem.setText(newItemLabel) self.actionNewAccountGroup.setEnabled(isSheet) self.actionMoveDown.setEnabled(isTransactionOrEntryTable) self.actionMoveUp.setEnabled(isTransactionOrEntryTable) self.actionDuplicateTransaction.setEnabled(isTransactionOrEntryTable) self.actionMakeScheduleFromSelected.setEnabled(isTransactionOrEntryTable) self.actionReconcileSelected.setEnabled(viewType == PaneType.Account and view.reconciliation_mode) self.actionShowNextView.setEnabled(self.model.current_pane_index < self.model.pane_count-1) self.actionShowPreviousView.setEnabled(self.model.current_pane_index > 0) self.actionShowSelectedAccount.setEnabled(isSheet or isTransactionOrEntryTable) self.actionNavigateBack.setEnabled(viewType == PaneType.Account) self.actionToggleReconciliationMode.setEnabled(canToggleReconciliation) self.actionToggleAccountExclusion.setEnabled(isSheet) def _updateUndoActions(self): if self.doc.can_undo(): self.actionUndo.setEnabled(True) self.actionUndo.setText(tr("Undo {0}").format(self.doc.undo_description())) else: self.actionUndo.setEnabled(False) self.actionUndo.setText(tr("Undo")) if self.doc.can_redo(): self.actionRedo.setEnabled(True) self.actionRedo.setText(tr("Redo {0}").format(self.doc.redo_description())) else: self.actionRedo.setEnabled(False) self.actionRedo.setText(tr("Redo")) # --- Actions # Document open/save/close def confirmDestructiveAction(self): # Asks whether the user wants to continue before continuing with an action that will replace # the current document. Will save the document as needed. Returns True if the action can # continue. if not self.model.document.is_dirty(): return True title = tr("Unsaved Document") msg = tr("Do you want to save your changes before continuing?") buttons = QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard result = QMessageBox.question(self.app.mainWindow, title, msg, buttons) if result == QMessageBox.Save: self.save() if self.model.document.is_dirty(): # "save as" was cancelled return False else: return True elif result == QMessageBox.Cancel: return False elif result == QMessageBox.Discard: return True def new(self): if not self.confirmDestructiveAction(): return self.model.close() self.documentPath = None self.model.clear() self.documentPathChanged() def open(self, docpath, initial=False): # initial flag is true when open() is called at the document's initialization. When that's # the case, we need to create a new document when we fail opening this one. if not self.confirmDestructiveAction(): return self.model.close() try: self.model.load_from_xml(docpath) self.documentPath = docpath except FileFormatError as e: QMessageBox.warning(self.app.mainWindow, tr("Cannot load file"), str(e)) if initial: self.new() self.documentPathChanged() self.recentDocuments.insertItem(docpath) def openDocument(self): title = tr("Select a document to load") filters = tr("moneyGuru Documents (*.moneyguru)") docpath, filetype = QFileDialog.getOpenFileName(self.app.mainWindow, title, '', filters) if docpath: self.open(docpath) def save(self): if self.documentPath is not None: self.model.save_to_xml(self.documentPath) else: self.saveAs() def saveAs(self): title = tr("Save As") filters = tr("moneyGuru Documents (*.moneyguru)") docpath = QFileDialog.getSaveFileName(self.app.mainWindow, title, '', filters)[0] if docpath: if not docpath.endswith('.moneyguru'): docpath += '.moneyguru' self.model.save_to_xml(docpath) self.documentPath = docpath self.documentPathChanged() self.recentDocuments.insertItem(docpath) # Views def showNetWorthTriggered(self): self.model.select_pane_of_type(PaneType.NetWorth) def showProfitLossTriggered(self): self.model.select_pane_of_type(PaneType.Profit) def showTransactionsTriggered(self): self.model.select_pane_of_type(PaneType.Transaction) def showSchedulesTriggered(self): self.model.select_pane_of_type(PaneType.Schedule) def showPreviousViewTriggered(self): self.model.select_previous_view() def showNextViewTriggered(self): self.model.select_next_view() # Document Edition def newItemTriggered(self): self.model.new_item() def newAccountGroupTriggered(self): self.model.new_group() def deleteItemTriggered(self): self.model.delete_item() def editItemTriggered(self): self.model.edit_item() def moveUpTriggered(self): self.model.move_up() def moveDownTriggered(self): self.model.move_down() # Misc def closeTabTriggered(self): self.model.close_pane(self.model.current_pane_index) def navigateBackTriggered(self): self.model.navigate_back() def jumpToAccountTriggered(self): self.model.jump_to_account() def makeScheduleFromSelectedTriggered(self): self.model.make_schedule_from_selected() def reconcileSelectedTriggered(self): self._activeView().etable.toggle_reconciled() def toggleReconciliationModeTriggered(self): self._activeView().toggle_reconciliation_mode() self._updateActionsState() def toggleAccountExclusionTriggered(self): viewType = self.model.pane_type(self.model.current_pane_index) if viewType in {PaneType.NetWorth, PaneType.Profit}: self._activeView().sheet.toggle_excluded() def toggleGraphTriggered(self): self.model.toggle_area_visibility(PaneArea.BottomGraph) def togglePieChartTriggered(self): self.model.toggle_area_visibility(PaneArea.RightChart) def columnsVisibilityButtonClicked(self): items = self.model.column_menu_items() if not items: return menu = QMenu() for i, (display, marked) in enumerate(items): action = menu.addAction(display) action.setCheckable(True) action.setChecked(marked) action.setData(i) action.triggered.connect(self.columnsMenuItemWasClicked) self._columnMenuHolder = menu # we need to hold a reference to it while it popups button = self.columnsVisibilityButton menu.popup(button.parentWidget().mapToGlobal(button.geometry().topLeft())) def columnsMenuItemWasClicked(self): action = self.sender() if action is not None: index = action.data() self.model.toggle_column_menu_item(index) def aboutTriggered(self): self.app.showAboutBox() def importDocument(self): title = tr("Select a document to import") filters = tr("Supported files (*.moneyguru *.ofx *.qfx *.qif *.csv *.txt);;All files (*)") docpath, filetype = QFileDialog.getOpenFileName(self.app.mainWindow, title, '', filters) # There's a strange glitch under GNOME where, right after the dialog is gone, the main # window isn't the active window, but it will become active if we give it enough time. If we # start showing the import window before that happens, we'll end up with an import window # under the main window, which is bad. Therefore, we process events until this happens. We # do this in a big forloop instead of a while to avoid a possible infinite loop. for i in range(10000): if self.app.mainWindow.isActiveWindow(): break QApplication.processEvents() if docpath: try: self.model.parse_file_for_import(docpath) except FileFormatError as e: QMessageBox.warning(self.app.mainWindow, tr("Cannot import file"), str(e)) # --- Other Signals def currentTabChanged(self, index): self.model.current_pane_index = index self._setTabIndex(index) def documentPathChanged(self): if self.documentPath: title = "moneyGuru ({})".format(self.documentPath) else: title = "moneyGuru" self.setWindowTitle(title) def tabCloseRequested(self, index): self.model.close_pane(index) def tabMoved(self, fromIndex, toIndex): # We don't refresh panes because tabMoved is apparently now called *during* drag operations. # If we start a full pane refresh during a drag operation, we segfault. self.model.move_pane(fromIndex, toIndex, refresh_panes=False) # --- document model --> view def query_for_schedule_scope(self): if QApplication.keyboardModifiers() & Qt.ShiftModifier: return ScheduleScope.Global if not self.app.model.show_schedule_scope_dialog: return ScheduleScope.Local dialog = ScheduleScopeDialog(self) return dialog.queryForScope() # --- model --> view def change_current_pane(self): self._setTabIndex(self.model.current_pane_index) def get_panel_view(self, model): if isinstance(model, CustomDateRangePanelModel): return CustomDateRangePanel(model, self) elif isinstance(model, CSVOptionsModel): return CSVOptionsWindow(model, self) elif isinstance(model, ImportWindowModel): return ImportWindow(model, self, self.app.prefs) else: return ExportPanel(model, self) def refresh_panes(self): while self.tabBar.count() < self.model.pane_count: self.tabBar.addTab('') for i in range(self.model.pane_count): pane_label = self.model.pane_label(i) pane_label = escapeamp(pane_label) self.tabBar.setTabText(i, pane_label) pane_type = self.model.pane_type(i) pane_view = self.model.pane_view(i) # Ensure that the view's "view" has been created and bound self._getViewforPane(pane_type, pane_view) iconname = PANETYPE2ICON.get(pane_type) icon = QIcon(QPixmap(':/{0}'.format(iconname))) if iconname else QIcon() self.tabBar.setTabIcon(i, icon) # It's important that we proceed with tab removal *after* we've completed tab initialization. # We're walking on eggshells here. refresh_panes() can be called in multiple situations, one # of them is during the opening of a document. When that happens when another document was # previously opened, all views' model are uninitalized and don't have their "view" attribute # set yet. If we proceed with the setCurrentIndex() call below before _getViewforPane() # could be called above, we get a crash. if self.tabBar.currentIndex() >= self.model.pane_count: # Normally, we don't touch the tabBar index here and wait for change_current_pane, # but when we remove tabs, it's possible that currentTabChanged end up being called and # then the tab selection is bugged. I tried disconnecting/reconnecting the signal, but # this is buggy. So when a selected tab is about to be removed and is out of bounds, # we change the selection to the last index in the model. We don't use # self.model.current_pane_index because in some cases, it's -1 and prevents this crash # preventer from preventing its crash. self.tabBar.setCurrentIndex(self.model.pane_count - 1) while self.tabBar.count() > self.model.pane_count: self.tabBar.removeTab(self.tabBar.count()-1) self.tabBar.setTabsClosable(self.model.pane_count > 1) def refresh_status_line(self): self.statusLabel.setText(self.model.status_line) def refresh_undo_actions(self): self._updateUndoActions() def restore_window_frame(self, frame): self.setGeometry(*frame) def save_window_frame(self): r = self.geometry() return (r.x(), r.y(), r.width(), r.height()) def show_message(self, msg): title = tr("Warning") QMessageBox.warning(self, title, msg) def update_area_visibility(self): hidden = self.model.hidden_areas graphimg = ':/graph_visibility_{}_16'.format('off' if PaneArea.BottomGraph in hidden else 'on') pieimg = ':/piechart_visibility_{}_16'.format('off' if PaneArea.RightChart in hidden else 'on') self.graphVisibilityButton.setIcon(QIcon(QPixmap(graphimg))) self.piechartVisibilityButton.setIcon(QIcon(QPixmap(pieimg))) def view_closed(self, index): self.tabBar.removeTab(index) self.tabBar.setTabsClosable(self.model.pane_count > 1)
class TassomaiUI(object): def __init__(self, main_window: QMainWindow): self.win = main_window def setupUi(self): self.win.setWindowTitle(f"Tassomai Automation v{__version__}") self.win.setWindowIcon(QIcon(path('images', 'logo.png'))) self.win.resize(665, 580) self.centralwidget = QWidget(self.win) self.formLayout = QFormLayout(self.centralwidget) self.formLayout.setContentsMargins(5, 0, 5, -1) self.topFrame = QFrame(self.centralwidget) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.topFrame.sizePolicy().hasHeightForWidth()) self.topFrame.setSizePolicy(sizePolicy) self.topFrame.setAutoFillBackground(True) self.topFrame.setFrameShape(QFrame.StyledPanel) self.topFrame.setFrameShadow(QFrame.Raised) self.gridLayout = QGridLayout(self.topFrame) self.tassomaiImage = QLabel(self.topFrame) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.tassomaiImage.sizePolicy().hasHeightForWidth()) self.tassomaiImage.setSizePolicy(sizePolicy) self.tassomaiImage.setPixmap(QPixmap(path('images', 'banner.png'))) self.gridLayout.addWidget(self.tassomaiImage, 0, 0, 1, 1) self.formLayout.setWidget(0, QFormLayout.SpanningRole, self.topFrame) self.tab = QTabWidget(self.centralwidget) self.main_tab = QWidget() self.automation_tab = QWidget() self.gridLayout_4 = QGridLayout(self.main_tab) self.gridLayout_4.setContentsMargins(0, 0, 0, 0) self.main_frame = QFrame(self.main_tab) self.main_frame.setAutoFillBackground(True) self.main_frame.setFrameShape(QFrame.StyledPanel) self.main_frame.setFrameShadow(QFrame.Raised) self.gridLayout_2 = QGridLayout(self.main_frame) self.gridLayout_2.setContentsMargins(5, 6, 2, -1) self.gridLayout_2.setVerticalSpacing(10) self.gridLayout_5 = QGridLayout(self.automation_tab) self.gridLayout_5.setContentsMargins(0, 0, 0, 0) self.automation_frame = QFrame(self.automation_tab) self.automation_frame.setAutoFillBackground(True) self.automation_frame.setFrameShape(QFrame.StyledPanel) self.automation_frame.setFrameShadow(QFrame.Raised) self.delayLayout = QHBoxLayout() self.delayLayout.setContentsMargins(0, 0, 0, 0) self.delayLayout.setSpacing(3) self.delay = QCheckBox(self.main_frame) font = QFont() font.setPointSize(10) self.delay.setFont(font) self.delayLayout.addWidget(self.delay) self.amountOfDelay = QDoubleSpinBox(self.main_frame) self.amountOfDelay.setMinimumWidth(70) self.amountOfDelay.setMaximum(25.00) self.delayLayout.addWidget(self.amountOfDelay) self.label03 = QLabel(self.main_frame) self.label03.setSizePolicy(sizePolicy) self.label03.setFont(font) self.delayLayout.addWidget(self.label03) self.amountOfDelay2 = QDoubleSpinBox(self.main_frame) self.amountOfDelay2.setMinimumWidth(70) self.amountOfDelay2.setMaximum(25.00) self.delayLayout.addWidget(self.amountOfDelay2) self.label3 = QLabel(self.main_frame) self.label3.setSizePolicy(sizePolicy) self.label3.setFont(font) self.delayLayout.addWidget(self.label3) self.whenDelay = QComboBox(self.main_frame) self.whenDelay.addItem("question") self.whenDelay.addItem("quiz") self.whenDelay.setMaximumWidth(100) self.delayLayout.addWidget(self.whenDelay) self.verticalSpacer1 = QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Expanding) self.delayLayout.addItem(self.verticalSpacer1) self.gridLayout_2.addLayout(self.delayLayout, 2, 0, 1, 1) self.randomnessLayout = QHBoxLayout() self.randomnessLayout.setContentsMargins(0, 0, 0, 0) self.randomnessLayout.setSpacing(3) self.randomness = QCheckBox(self.main_frame) self.randomness.setFont(font) self.randomness.setMaximumWidth(338) self.randomnessLayout.addWidget(self.randomness) self.randomnessAmount = QSpinBox(self.main_frame) self.randomnessAmount.setMinimumWidth(70) self.randomnessAmount.setMaximum(600) self.randomnessLayout.addWidget(self.randomnessAmount) self.label4 = QLabel(self.main_frame) self.label4.setSizePolicy(sizePolicy) self.label4.setFont(font) self.randomnessLayout.addWidget(self.label4) self.gridLayout_2.addLayout(self.randomnessLayout, 3, 0, 1, 1) self.dailyGoal = QCheckBox(self.main_frame) font = QFont() font.setPointSize(10) self.dailyGoal.setFont(font) self.gridLayout_2.addWidget(self.dailyGoal, 4, 0, 1, 1) self.bonusGoal = QCheckBox(self.main_frame) self.bonusGoal.setFont(font) self.gridLayout_2.addWidget(self.bonusGoal, 5, 0, 1, 1) self.horizontalLayout = QHBoxLayout() self.label1 = QLabel(self.main_frame) sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label1.sizePolicy().hasHeightForWidth()) self.label1.setSizePolicy(sizePolicy) font = QFont() font.setPointSize(10) self.label1.setFont(font) self.horizontalLayout.addWidget(self.label1) self.maxQuizes = QSpinBox(self.main_frame) self.maxQuizes.setMinimum(1) self.maxQuizes.setMaximum(1000000) self.maxQuizes.setProperty("value", 1000) self.horizontalLayout.addWidget(self.maxQuizes) self.label2 = QLabel(self.main_frame) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label2.sizePolicy().hasHeightForWidth()) self.label2.setSizePolicy(sizePolicy) font = QFont() font.setPointSize(10) self.label2.setFont(font) self.horizontalLayout.addWidget(self.label2) self.gridLayout_2.addLayout(self.horizontalLayout, 1, 0, 1, 1) self.userBox = QGroupBox(self.main_frame) font = QFont() font.setPointSize(9) font.setBold(False) font.setWeight(50) self.userBox.setFont(font) self.gridLayout_3 = QGridLayout(self.userBox) self.emailTassomaiLabel = QLabel(self.userBox) self.gridLayout_3.addWidget(self.emailTassomaiLabel, 0, 0, 1, 1) self.emailTassomai = QLineEdit(self.userBox) self.gridLayout_3.addWidget(self.emailTassomai, 0, 1, 1, 1) self.passwordTassomaiLabel = QLabel(self.userBox) self.gridLayout_3.addWidget(self.passwordTassomaiLabel, 1, 0, 1, 1) self.passwordTassomai = QLineEdit(self.userBox) self.passwordTassomai.setEchoMode(QLineEdit.Password) self.gridLayout_3.addWidget(self.passwordTassomai, 1, 1, 1, 1) self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.gridLayout_3.addItem(self.verticalSpacer, 2, 0, 1, 1) self.gridLayout_4.addWidget(self.main_frame, 0, 0, 1, 1) self.gridLayout_5.addWidget(self.automation_frame, 0, 0, 1, 1) self.tab.addTab(self.main_tab, "") self.tab.addTab(self.automation_tab, "") self.formLayout.setWidget(1, QFormLayout.SpanningRole, self.tab) self.gridLayout_2.addWidget(self.userBox, 0, 0, 1, 1) self.buttonsLayout = QHBoxLayout() self.bottom_frame = QFrame(self.centralwidget) self.bottom_frame.setFrameShape(QFrame.StyledPanel) self.bottom_frame.setFrameShadow(QFrame.Raised) self.gridLayout_7 = QGridLayout(self.bottom_frame) self.gridLayout_7.setContentsMargins(0, 0, 0, 0) self.startButton = QPushButton(self.bottom_frame) self.buttonsLayout.addWidget(self.startButton) self.stopButton = QPushButton(self.bottom_frame) self.buttonsLayout.addWidget(self.stopButton) self.gridLayout_7.addLayout(self.buttonsLayout, 0, 0, 1, 1) self.output = QTextEdit(self.bottom_frame) self.gridLayout_7.addWidget(self.output, 1, 0, 1, 1) self.formLayout.setWidget(2, QFormLayout.SpanningRole, self.bottom_frame) self.win.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(self.win) self.menubar.setGeometry(QRect(0, 0, 665, 21)) self.tools_menu = QMenu(self.menubar) self.uninstall_option = QAction() self.tools_menu.addAction(self.uninstall_option) self.menubar.addAction(self.tools_menu.menuAction()) self.win.setMenuBar(self.menubar) self.createTable() self.retranslateUi() self.tab.setCurrentIndex(0) self.tab.currentChanged['int'].connect(lambda k: self.bottom_frame.hide() if k != 0 else self.bottom_frame.show()) QMetaObject.connectSlotsByName(self.win) def retranslateUi(self): self.dailyGoal.setChecked(True) self.dailyGoal.setText("Finish when daily goal complete") self.bonusGoal.setText("Finish when bonus goal complete") self.delay.setText("Add a delay between") self.label03.setText("and") self.label3.setText("seconds between each") self.randomness.setText("Make it so that you answer a question incorrectly every") self.label4.setText("questions") self.label1.setText("Only do a maximum of ") self.label2.setText(" quiz(s)") self.userBox.setTitle("User Settings") self.passwordTassomaiLabel.setText("Password for Tassomai login") self.emailTassomaiLabel.setText("Email for Tassomai login") self.tab.setTabText(self.tab.indexOf(self.main_tab), "General") self.tab.setTabText(self.tab.indexOf(self.automation_tab), "Automation") self.startButton.setText("Start Automation") self.stopButton.setText("Stop Automation") self.tools_menu.setTitle("Tools") self.uninstall_option.setText("Uninstall (coming soon)") self.output.setReadOnly(True) self.startButton.setEnabled(True) self.stopButton.setEnabled(False) self.output.setHtml("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; }\n" "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal;\">\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">-------------------------------------------</p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:8pt; font-weight:600; text-decoration: underline; color:#14860a;\">All output will go here<br /></span></p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">-------------------------------------------</p>\n" ) def createTable(self): self.table = QTableWidget(self.automation_tab) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setAlternatingRowColors(True) self.table.setSelectionMode(QAbstractItemView.SingleSelection) self.table.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self.table.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.table.setShowGrid(True) self.table.setGridStyle(Qt.DashLine) self.table.setRowCount(999999) self.table.setColumnCount(6) for i in range(6): self.table.setHorizontalHeaderItem(i, QTableWidgetItem()) self.table.horizontalHeaderItem(i).setTextAlignment(Qt.AlignLeft) for i in range(6): self.table.setItem(0, i, QTableWidgetItem()) self.table.setItem(1, i, QTableWidgetItem()) self.table.horizontalHeader().setVisible(True) self.table.horizontalHeader().setHighlightSections(True) self.table.verticalHeader().setVisible(False) self.table.verticalHeader().setHighlightSections(True) self.gridLayout_5.addWidget(self.table, 0, 0, 1, 1) headers = ["Quiz", "Num", "Question", "Correct", "Time", "Answer"] for header in headers: item = self.table.horizontalHeaderItem(headers.index(header)) item.setText(header) item.setSizeHint(QSize(25, 25)) self.table.setColumnWidth(0, 40) self.table.setColumnWidth(1, 40) self.table.setColumnWidth(2, 175) self.table.setColumnWidth(3, 80) self.table.setColumnWidth(4, 80) self.table.setColumnWidth(5, 230)
class DirectoriesDialog(QMainWindow): def __init__(self, app, **kwargs): super().__init__(None, **kwargs) self.app = app self.lastAddedFolder = platform.INITIAL_FOLDER_IN_DIALOGS self.recentFolders = Recent(self.app, 'recentFolders') self._setupUi() self._updateScanTypeList() self.directoriesModel = DirectoriesModel(self.app.model.directory_tree, view=self.treeView) self.directoriesDelegate = DirectoriesDelegate() self.treeView.setItemDelegate(self.directoriesDelegate) self._setupColumns() self.app.recentResults.addMenu(self.menuLoadRecent) self.app.recentResults.addMenu(self.menuRecentResults) self.recentFolders.addMenu(self.menuRecentFolders) self._updateAddButton() self._updateRemoveButton() self._updateLoadResultsButton() self._updateActionsState() self._setupBindings() def _setupBindings(self): self.appModeRadioBox.itemSelected.connect(self.appModeButtonSelected) self.showPreferencesButton.clicked.connect(self.app.actionPreferences.trigger) self.scanButton.clicked.connect(self.scanButtonClicked) self.loadResultsButton.clicked.connect(self.actionLoadResults.trigger) self.addFolderButton.clicked.connect(self.actionAddFolder.trigger) self.removeFolderButton.clicked.connect(self.removeFolderButtonClicked) self.treeView.selectionModel().selectionChanged.connect(self.selectionChanged) self.app.recentResults.itemsChanged.connect(self._updateLoadResultsButton) self.recentFolders.itemsChanged.connect(self._updateAddButton) self.recentFolders.mustOpenItem.connect(self.app.model.add_directory) self.directoriesModel.foldersAdded.connect(self.directoriesModelAddedFolders) self.app.willSavePrefs.connect(self.appWillSavePrefs) def _setupActions(self): # (name, shortcut, icon, desc, func) ACTIONS = [ ('actionLoadResults', 'Ctrl+L', '', tr("Load Results..."), self.loadResultsTriggered), ('actionShowResultsWindow', '', '', tr("Results Window"), self.app.showResultsWindow), ('actionAddFolder', '', '', tr("Add Folder..."), self.addFolderTriggered), ] createActions(ACTIONS, self) def _setupMenu(self): self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 42, 22)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle(tr("File")) self.menuView = QMenu(self.menubar) self.menuView.setTitle(tr("View")) self.menuHelp = QMenu(self.menubar) self.menuHelp.setTitle(tr("Help")) self.menuLoadRecent = QMenu(self.menuFile) self.menuLoadRecent.setTitle(tr("Load Recent Results")) self.setMenuBar(self.menubar) self.menuFile.addAction(self.actionLoadResults) self.menuFile.addAction(self.menuLoadRecent.menuAction()) self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionClearPictureCache) self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionQuit) self.menuView.addAction(self.app.actionPreferences) self.menuView.addAction(self.actionShowResultsWindow) self.menuView.addAction(self.app.actionIgnoreList) self.menuHelp.addAction(self.app.actionShowHelp) self.menuHelp.addAction(self.app.actionOpenDebugLog) self.menuHelp.addAction(self.app.actionAbout) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) # Recent folders menu self.menuRecentFolders = QMenu() self.menuRecentFolders.addAction(self.actionAddFolder) self.menuRecentFolders.addSeparator() # Recent results menu self.menuRecentResults = QMenu() self.menuRecentResults.addAction(self.actionLoadResults) self.menuRecentResults.addSeparator() def _setupUi(self): self.setWindowTitle(self.app.NAME) self.resize(420, 338) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) hl = QHBoxLayout() label = QLabel(tr("Application Mode:"), self) label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hl.addWidget(label) self.appModeRadioBox = RadioBox( self, items=[tr("Standard"), tr("Music"), tr("Picture")], spread=False ) hl.addWidget(self.appModeRadioBox) self.verticalLayout.addLayout(hl) hl = QHBoxLayout() hl.setAlignment(Qt.AlignLeft) label = QLabel(tr("Scan Type:"), self) label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hl.addWidget(label) self.scanTypeComboBox = QComboBox(self) self.scanTypeComboBox.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.scanTypeComboBox.setMaximumWidth(400) hl.addWidget(self.scanTypeComboBox) self.showPreferencesButton = QPushButton(tr("More Options"), self.centralwidget) self.showPreferencesButton.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hl.addWidget(self.showPreferencesButton) self.verticalLayout.addLayout(hl) self.promptLabel = QLabel(tr("Select folders to scan and press \"Scan\"."), self.centralwidget) self.verticalLayout.addWidget(self.promptLabel) self.treeView = QTreeView(self.centralwidget) self.treeView.setSelectionMode(QAbstractItemView.ExtendedSelection) self.treeView.setSelectionBehavior(QAbstractItemView.SelectRows) self.treeView.setAcceptDrops(True) triggers = QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed\ | QAbstractItemView.SelectedClicked self.treeView.setEditTriggers(triggers) self.treeView.setDragDropOverwriteMode(True) self.treeView.setDragDropMode(QAbstractItemView.DropOnly) self.treeView.setUniformRowHeights(True) self.verticalLayout.addWidget(self.treeView) self.horizontalLayout = QHBoxLayout() self.removeFolderButton = QPushButton(self.centralwidget) self.removeFolderButton.setIcon(QIcon(QPixmap(":/minus"))) self.removeFolderButton.setShortcut("Del") self.horizontalLayout.addWidget(self.removeFolderButton) self.addFolderButton = QPushButton(self.centralwidget) self.addFolderButton.setIcon(QIcon(QPixmap(":/plus"))) self.horizontalLayout.addWidget(self.addFolderButton) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.loadResultsButton = QPushButton(self.centralwidget) self.loadResultsButton.setText(tr("Load Results")) self.horizontalLayout.addWidget(self.loadResultsButton) self.scanButton = QPushButton(self.centralwidget) self.scanButton.setText(tr("Scan")) self.scanButton.setDefault(True) self.horizontalLayout.addWidget(self.scanButton) self.verticalLayout.addLayout(self.horizontalLayout) self.setCentralWidget(self.centralwidget) self._setupActions() self._setupMenu() if self.app.prefs.directoriesWindowRect is not None: self.setGeometry(self.app.prefs.directoriesWindowRect) else: moveToScreenCenter(self) def _setupColumns(self): header = self.treeView.header() header.setStretchLastSection(False) header.setSectionResizeMode(0, QHeaderView.Stretch) header.setSectionResizeMode(1, QHeaderView.Fixed) header.resizeSection(1, 100) def _updateActionsState(self): self.actionShowResultsWindow.setEnabled(self.app.resultWindow is not None) def _updateAddButton(self): if self.recentFolders.isEmpty(): self.addFolderButton.setMenu(None) else: self.addFolderButton.setMenu(self.menuRecentFolders) def _updateRemoveButton(self): indexes = self.treeView.selectedIndexes() if not indexes: self.removeFolderButton.setEnabled(False) return self.removeFolderButton.setEnabled(True) def _updateLoadResultsButton(self): if self.app.recentResults.isEmpty(): self.loadResultsButton.setMenu(None) else: self.loadResultsButton.setMenu(self.menuRecentResults) def _updateScanTypeList(self): try: self.scanTypeComboBox.currentIndexChanged[int].disconnect(self.scanTypeChanged) except TypeError: # Not connected, ignore pass self.scanTypeComboBox.clear() scan_options = self.app.model.SCANNER_CLASS.get_scan_options() for scan_option in scan_options: self.scanTypeComboBox.addItem(scan_option.label) SCAN_TYPE_ORDER = [so.scan_type for so in scan_options] selected_scan_type = self.app.prefs.get_scan_type(self.app.model.app_mode) scan_type_index = SCAN_TYPE_ORDER.index(selected_scan_type) self.scanTypeComboBox.setCurrentIndex(scan_type_index) self.scanTypeComboBox.currentIndexChanged[int].connect(self.scanTypeChanged) self.app._update_options() #--- QWidget overrides def closeEvent(self, event): event.accept() if self.app.model.results.is_modified: title = tr("Unsaved results") msg = tr("You have unsaved results, do you really want to quit?") if not self.app.confirm(title, msg): event.ignore() if event.isAccepted(): QApplication.quit() #--- Events def addFolderTriggered(self): title = tr("Select a folder to add to the scanning list") flags = QFileDialog.ShowDirsOnly dirpath = str(QFileDialog.getExistingDirectory(self, title, self.lastAddedFolder, flags)) if not dirpath: return self.lastAddedFolder = dirpath self.app.model.add_directory(dirpath) self.recentFolders.insertItem(dirpath) def appModeButtonSelected(self, index): if index == 2: mode = AppMode.Picture elif index == 1: mode = AppMode.Music else: mode = AppMode.Standard self.app.model.app_mode = mode self._updateScanTypeList() def appWillSavePrefs(self): self.app.prefs.directoriesWindowRect = self.geometry() def directoriesModelAddedFolders(self, folders): for folder in folders: self.recentFolders.insertItem(folder) def loadResultsTriggered(self): title = tr("Select a results file to load") files = ';;'.join([tr("dupeGuru Results (*.dupeguru)"), tr("All Files (*.*)")]) destination = QFileDialog.getOpenFileName(self, title, '', files) if destination: self.app.model.load_from(destination) self.app.recentResults.insertItem(destination) def removeFolderButtonClicked(self): self.directoriesModel.model.remove_selected() def scanButtonClicked(self): if self.app.model.results.is_modified: title = tr("Start a new scan") msg = tr("You have unsaved results, do you really want to continue?") if not self.app.confirm(title, msg): return self.app.model.start_scanning() def scanTypeChanged(self, index): scan_options = self.app.model.SCANNER_CLASS.get_scan_options() self.app.prefs.set_scan_type(self.app.model.app_mode, scan_options[index].scan_type) self.app._update_options() def selectionChanged(self, selected, deselected): self._updateRemoveButton()
class MainWindow(QMainWindow): def __init__(self, ui_template_path, *args, **kwargs): """ Initialise the MainWindow """ super(MainWindow, self).__init__(*args, **kwargs) # Import settings self.ui_template = json.load(open(ui_template_path, 'r')) self.settings = import_settings() self.setWindowTitle('Worms Visualiser') self.setWindowIcon(QIcon(':resources/icons/main/worm.png')) self.setGeometry(350, 40, 1200, 980) # Status bar self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) # Error message on the right of the status bar self.error_label = QLabel() self.error_label.setStyleSheet('color: darkred') self.status_bar.addPermanentWidget(self.error_label) # Menu bar self.menu_bar = QMenuBar() self.setMenuBar(self.menu_bar) # self.menu_bar.setGeometry(QRect(0, 0, 800, 21)) # File menu self.menu_file = QMenu() self.menu_file.setTitle('File') self.menu_bar.addAction(self.menu_file.menuAction()) # File menu --> Exit self.exit_action = QAction() self.exit_action.setIcon( QIcon(':resources/icons/menu/icons8-exit-32.png')) self.exit_action.triggered.connect(self.close) self.exit_action.setText('Exit') self.exit_action.setStatusTip('Exit the application') self.menu_file.addAction(self.exit_action) # Layout self.grid_layout = QGridLayout() self.grid_layout.setColumnStretch(1, 1) # Central widget self.central_widget = QWidget() self.central_widget.setLayout(self.grid_layout) self.setCentralWidget(self.central_widget) """ Groups """ self.groups = {} for group in self.ui_template['groups']: group_object = groupType[group['type']](group) self.groups[group['name']] = group_object self.grid_layout.addWidget(group_object, group['row'], group['col']) """ Signals """ self.groups[ 'match_log_group'].select_new_directory_button.clicked.connect( self.groups['match_log_group'].change_directory) self.groups['match_log_group'].match_logs_list.selectionModel( ).selectionChanged.connect( self.groups['match_view_group'].match_selected) self.groups[ 'match_log_group'].refresh_directory_button.clicked.connect( self.groups['match_log_group'].directory_refreshed) self.groups['match_view_group'].rounds_list.selectionModel( ).selectionChanged.connect( self.groups['match_view_group'].round_selected)
class GenEditor(QMainWindow): def __init__(self): super().__init__() self.res_file = None self.setup_ui() self.texture_archive = None try: self.configuration = read_config() print("Config file loaded") except FileNotFoundError as e: print("No config file found, creating default config...") self.configuration = make_default_config() self.pathsconfig = self.configuration["default paths"] #self.editorconfig = self.configuration["gen editor"] self.current_gen_path = None self.current_coordinates = None self.editing_windows = {} self.add_object_window = None self.object_to_be_added = None self.edit_spawn_window = None self._window_title = "" self._user_made_change = False self._justupdatingselectedobject = False self.addobjectwindow_last_selected = None self.lastshow = None self.modelindices = {} @catch_exception def reset(self): self.object_to_be_added = None self.model_list.clear() self.res_file = None self.current_coordinates = None self.editing_windows = {} self.current_gen_path = None self._window_title = "" self._user_made_change = False self.addobjectwindow_last_selected = None self.waterbox_renderer.reset() if self.texture_archive is not None: self.texture_archive.reset() if self.res_file is not None: del self.res_file self.res_file = None def set_base_window_title(self, name): self._window_title = name if name != "": self.setWindowTitle("Battalion Wars Model Viewer - " + name) else: self.setWindowTitle("Battalion Wars Model Viewer") def set_has_unsaved_changes(self, hasunsavedchanges): return def setup_ui(self): self.resize(1000, 800) self.set_base_window_title("") self.setup_ui_menubar() self.setup_ui_toolbar() self.centralwidget = QWidget(self) self.centralwidget.setObjectName("centralwidget") self.setCentralWidget(self.centralwidget) #self.pikmin_gen_view = GenMapViewer(self.centralwidget) self.waterbox_renderer = RenderWindow(self.centralwidget) self.model_list = QtWidgets.QListWidget(self.centralwidget) self.waterbox_renderer.setMinimumWidth(400) self.model_list.setMaximumWidth(200) self.model_list.setFocusPolicy(Qt.NoFocus) self.horizontalLayout = QHBoxLayout(self.centralwidget) self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.addWidget(self.waterbox_renderer) spacerItem = QSpacerItem(10, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.horizontalLayout.addItem(spacerItem) self.horizontalLayout.addWidget(self.model_list) self.statusbar = QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.connect_actions() def setup_ui_menubar(self): self.menubar = QMenuBar(self) self.file_menu = QMenu(self) self.file_menu.setTitle("File") self.file_load_action = QAction("Load", self) self.save_file_action = QAction("Save", self) self.save_file_as_action = QAction("Save As", self) #self.save_file_action.setShortcut("Ctrl+S") #self.file_load_action.setShortcut("Ctrl+O") #self.save_file_as_action.setShortcut("Ctrl+Alt+S") self.file_load_action.triggered.connect(self.button_load_level) self.file_menu.addAction(self.file_load_action) # Misc self.model_menu = QMenu(self.menubar) self.model_menu.setTitle("Model") self.export_model_obj_action = QAction("Export current as OBJ", self) self.export_model_obj_action.triggered.connect(self.export_model_obj) self.model_menu.addAction(self.export_model_obj_action) self.export_model_obj_batch_action = QAction("Export All as OBJ", self) self.export_model_obj_batch_action.triggered.connect( self.export_model_obj_batch) self.model_menu.addAction(self.export_model_obj_batch_action) self.texturemenu = QMenu(self.menubar) self.texturemenu.setTitle("Textures") self.export_tex_action = QAction("Export All Textures as PNG", self) self.export_tex_action.triggered.connect(self.export_all_textures) self.texturemenu.addAction(self.export_tex_action) self.menubar.addAction(self.file_menu.menuAction()) self.menubar.addAction(self.model_menu.menuAction()) self.menubar.addAction(self.texturemenu.menuAction()) #self.menubar.addAction(self.collision_menu.menuAction()) #self.menubar.addAction(self.misc_menu.menuAction()) self.setMenuBar(self.menubar) @catch_exception def export_model_obj(self, bool): filepath = QFileDialog.getExistingDirectory( self, "Open Directory", self.pathsconfig["exportedModels"]) if filepath: if self.waterbox_renderer.main_model is not None: self.waterbox_renderer.main_model.export_obj( filepath, self.waterbox_renderer.texarchive) self.pathsconfig["exportedModels"] = filepath save_cfg(self.configuration) @catch_exception_with_dialog def export_model_obj_batch(self, bool): filepath = QFileDialog.getExistingDirectory( self, "Open Directory", self.pathsconfig["exportedModels"]) if filepath: i = 0 total = len(self.res_file.models) for model in self.res_file.models: QtCore.QCoreApplication.processEvents() i += 1 name = str(bytes(model.res_name).strip(), encoding="ascii") self.waterbox_renderer.create_drawlist( model, isbw1=self.res_file.is_bw()) #self.waterbox_renderer.do_redraw() folderpath = os.path.join(filepath, name) os.makedirs(folderpath, exist_ok=True) self.statusbar.showMessage( "Exporting {0} ({1} out of {2})".format(name, i, total)) self.waterbox_renderer.main_model.export_obj( folderpath, self.waterbox_renderer.texarchive) self.waterbox_renderer.do_redraw() self.pathsconfig["exportedModels"] = filepath save_cfg(self.configuration) self.statusbar.showMessage("Finished", 3000) def setup_ui_toolbar(self): pass def connect_actions(self): #self.model_list.itemClicked.connect(self.select_model) self.model_list.itemSelectionChanged.connect(self.select_model) #self.waterbox_renderer.camera_moved.connect(self.update_cam_pos) return @catch_exception_with_dialog def export_all_textures(self, _): if self.res_file is None: return filepath = QFileDialog.getExistingDirectory( self, "Open Directory", self.pathsconfig["exportedModels"]) isbw = self.res_file.is_bw() curr = 0 total_tex = len(self.texture_archive.textures) if filepath and self.texture_archive is not None: for texname, texentry in self.texture_archive.textures.items(): curr += 1 QtCore.QCoreApplication.processEvents() tex = Texture(texname) if isbw: tex.from_file_bw1(texentry.fileobj) else: tex.from_file(texentry.fileobj) filename = str(texname.strip(b"\x00"), encoding="ascii") + ".png" outpath = os.path.join(filepath, filename) tex.dump_to_file(outpath) self.statusbar.showMessage("Extracted {0} ({1} of {2})".format( filename, curr, total_tex)) self.statusbar.showMessage("Finished", 5000) self.pathsconfig["exportedModels"] = filepath #@catch_exception def button_load_level(self): filepath, choosentype = QFileDialog.getOpenFileName( self, "Open File", self.pathsconfig["resourceFiles"], "Resource Files (*.res;*.res.gz);;All files (*)") if filepath: print("Resetting editor") self.reset() print("Reset done") print("Chosen file type:", choosentype) if filepath.endswith(".gz"): openfunc = gzip.open else: openfunc = open with openfunc(filepath, "rb") as f: try: self.res_file = BWArchive(f) self.texture_archive = TextureArchive(self.res_file) self.modelindices = {} modellist = [] for model in self.res_file.models: name = str(model.res_name, encoding="ascii") modellist.append(name) self.modelindices[name] = len(modellist) - 1 modellist.sort() for name in modellist: self.model_list.addItem(name) self.waterbox_renderer.texarchive = self.texture_archive print("File loaded") # self.bw_map_screen.update() # path_parts = path.split(filepath) self.set_base_window_title(filepath) self.pathsconfig["resourceFiles"] = filepath save_cfg(self.configuration) self.current_gen_path = filepath except Exception as error: self.modelindices = {} print("Error appeared while loading:", error) traceback.print_exc() open_error_dialog(str(error), self) @catch_exception_with_dialog def select_model(self): item = self.model_list.currentItem().text() index = self.modelindices[item] self.waterbox_renderer.create_drawlist(self.res_file.models[index], isbw1=self.res_file.is_bw()) self.waterbox_renderer.do_redraw() def keyPressEvent(self, event: QtGui.QKeyEvent): if event.key() == Qt.Key_Shift: self.waterbox_renderer.shift_is_pressed = True if event.key() == Qt.Key_W: self.waterbox_renderer.MOVE_FORWARD = 1 elif event.key() == Qt.Key_S: self.waterbox_renderer.MOVE_BACKWARD = 1 elif event.key() == Qt.Key_A: self.waterbox_renderer.MOVE_LEFT = 1 elif event.key() == Qt.Key_D: self.waterbox_renderer.MOVE_RIGHT = 1 elif event.key() == Qt.Key_Q: self.waterbox_renderer.MOVE_UP = 1 elif event.key() == Qt.Key_E: self.waterbox_renderer.MOVE_DOWN = 1 elif event.key() == Qt.Key_R: self.waterbox_renderer.ROTATE_LEFT = 1 elif event.key() == Qt.Key_T: self.waterbox_renderer.ROTATE_RIGHT = 1 elif event.key() == Qt.Key_Up: row = self.model_list.currentRow() - 1 if row < 0: row = 0 self.model_list.setCurrentRow(row) elif event.key() == Qt.Key_Down: row = self.model_list.currentRow() + 1 if self.res_file is None: row = 0 elif row >= len(self.res_file.models): row = len(self.res_file.models) - 1 self.model_list.setCurrentRow(row) def keyReleaseEvent(self, event: QtGui.QKeyEvent): if event.key() == Qt.Key_Shift: self.waterbox_renderer.shift_is_pressed = False if event.key() == Qt.Key_W: self.waterbox_renderer.MOVE_FORWARD = 0 elif event.key() == Qt.Key_S: self.waterbox_renderer.MOVE_BACKWARD = 0 elif event.key() == Qt.Key_A: self.waterbox_renderer.MOVE_LEFT = 0 elif event.key() == Qt.Key_D: self.waterbox_renderer.MOVE_RIGHT = 0 elif event.key() == Qt.Key_Q: self.waterbox_renderer.MOVE_UP = 0 elif event.key() == Qt.Key_E: self.waterbox_renderer.MOVE_DOWN = 0 elif event.key() == Qt.Key_R: self.waterbox_renderer.ROTATE_LEFT = 0 elif event.key() == Qt.Key_T: self.waterbox_renderer.ROTATE_RIGHT = 0
class MSOTable(QWidget): def __init__(self, db_name, tab_project, method): QWidget.__init__(self) self.tab_project = tab_project self.method = method self.__connector_mso__ = ConnectorMSO(db_name) self.__return_mso__ = ReturnMSO(db_name) self.db_name = db_name self.__variables__() self.__component__() def __variables__(self): self.columns = ['선택'] + self.__return_mso__.Columns() self.dataframe = self.__return_mso__.Dataframe() self.checked = [] self.edited = [] def __component__(self): self.__menubar__() self.__table__() self.__layout__() def __menubar__(self): action_insert = QAction('추가', self) action_insert.setShortcut('Alt+1') action_delete = QAction('삭제', self) action_delete.setShortcut('Alt+2') action_save = QAction('저장', self) action_save.setShortcut('Ctrl+S') action_insert.triggered.connect(self.Insert) action_delete.triggered.connect(self.Delete) action_save.triggered.connect(self.Save) self.menubar = QMenuBar(self) self.menubar.addAction(action_insert) self.menubar.addAction(action_delete) self.menubar.addAction(action_save) def Insert(self): row = self.table.rowCount() if row == 0: number = 1 elif row != 0: number = int(self.table.item(row - 1, 1).text()) + 1 item = QTableWidgetItem(str(number)) item.setFlags(Qt.ItemIsEditable) item.setTextAlignment(Qt.AlignCenter) self.table.insertRow(row) self.table.setRowHeight(row, 50) self.__checkbox__(self.table, row, 0) self.table.setItem(row, 1, item) item = QTableWidgetItem('') item.setTextAlignment(Qt.AlignCenter) self.table.setItem(row, 2, item) self.__connector_mso__.Insert(number) def __except__(self, row): for edited in self.edited: if row == edited[0]: self.edited.remove(edited) def Delete(self): self.checked.sort(reverse=True) for row in self.checked: self.__except__(row) number = int(self.table.item(row, 1).text()) self.__connector_mso__.Delete(number) self.table.removeRow(row) self.checked.clear() def Save(self): edited = list(set(map(tuple, self.edited))) for row, col in edited: number = int(self.table.item(row, 1).text()) if col == 2: value = self.table.item(row, col).text() self.__connector_mso__.Update(number, '논리번호', value) elif col == 3: value = self.table.item(row, col).text() self.__connector_mso__.Update(number, '영향기능', value) elif col == 4: value = self.table.item(row, col).text() self.__connector_mso__.Update(number, '기기조합', value) elif col == 5: value = self.table.item(row, col).text() self.__connector_mso__.Update(number, '비고', value) self.edited.clear() self.method() def __checkbox__(self, table, row, col): checkboxitem = CheckboxItem() checkbox = Checkbox(checkboxitem) checkbox.stateChanged.connect(self.Checked) table.setItem(row, col, checkboxitem) table.setCellWidget(row, col, checkbox) def Checked(self, check): row = self.table.currentRow() if check == 2: self.checked.append(row) elif check == 0: self.checked.remove(row) def __table__(self): self.table = QTableWidget() self.table.setRowCount(0) self.table.setColumnCount(len(self.columns)) self.table.setHorizontalHeaderLabels(self.columns) self.table.setAlternatingRowColors(True) style = "QHeaderView::section {font-weight: bold; border: 2px black;}" self.table.setStyleSheet(style) for row, lst in enumerate(self.dataframe.values): self.table.insertRow(row) self.table.setRowHeight(row, 50) self.__checkbox__(self.table, row, 0) for col, data in enumerate(lst): if col == 0: item = QTableWidgetItem(str(data)) item.setFlags(Qt.ItemIsEditable) item.setTextAlignment(Qt.AlignCenter) elif col in [2, 3, 4]: item = QTableWidgetItem(str(data)) else: item = QTableWidgetItem(str(data)) item.setTextAlignment(Qt.AlignCenter) self.table.setItem(row, col + 1, item) self.table.hideColumn(1) self.table.resizeColumnsToContents() self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setStretchLastSection(True) self.table.cellChanged.connect(self.Edited) def Edited(self, row, col): if col != 0: self.edited.append([row, col]) def __layout__(self): layout = QVBoxLayout() layout.addWidget(QLabel('※ MSO 논리 정보\n')) layout.addWidget(self.menubar) layout.addWidget(self.table) self.setLayout(layout)
class Ui_MainWindow(object): nameFileWave = '' overlap = 0.4 nperseg = 512 window = 'hamming' pause = False regionPause = False deletePlotFragment = True def setupUi(self, MainWindow): MainWindow.setGeometry(450, 50, 1000, 785) MainWindow.setWindowTitle("CFS") self.mainMenu = QMenuBar(MainWindow) self.mainMenu.setGeometry(QRect(0, 0, 1000, 21)) self.fileMenu = QMenu('&Dzwiek', self.mainMenu) MainWindow.setMenuBar(self.mainMenu) self.actionOpenFile = QAction('&Wczytaj', MainWindow) self.actionOpenFile.setShortcut('Ctrl+W') self.actionOpenFile.setStatusTip('Wczytaj dzwięk') self.actionOpenFile.triggered.connect(self.fileName) self.fileMenu.addSeparator() self.fileMenu.addAction(self.actionOpenFile) self.mainMenu.addAction(self.fileMenu.menuAction()) self.centralwidget = QWidget(MainWindow) self.groupBoxOdtwarzacz = QGroupBox(self.centralwidget) self.groupBoxOdtwarzacz.setTitle("Odtwarzacz:") self.groupBoxOdtwarzacz.setGeometry(QRect(10, 20, 171, 111)) self.pushButtonPlay = QPushButton(self.groupBoxOdtwarzacz) self.pushButtonPlay.setGeometry(QRect(20, 80, 31, 23)) self.pushButtonPlay.setText("Play") self.pushButtonPlay.clicked.connect(self.filePlay) self.pushButtonStop = QPushButton(self.groupBoxOdtwarzacz) self.pushButtonStop.setGeometry(QRect(110, 80, 31, 23)) self.pushButtonStop.setText("Stop") self.pushButtonStop.clicked.connect(self.fileStop) self.pushButtonPause = QPushButton(self.groupBoxOdtwarzacz) self.pushButtonPause.setGeometry(QRect(60, 80, 41, 23)) self.pushButtonPause.setText("Pause") self.pushButtonPause.clicked.connect(self.filePause) self.radioButtonCalosc = QRadioButton(self.groupBoxOdtwarzacz) self.radioButtonCalosc.setGeometry(QRect(10, 20, 91, 20)) self.radioButtonCalosc.setText("całe nagranie") self.radioButtonCalosc.setChecked(True) self.radioButtonFragment = QRadioButton(self.groupBoxOdtwarzacz) self.radioButtonFragment.setGeometry(QRect(10, 40, 161, 17)) self.radioButtonFragment.setText("wybrany przedział nagrania") self.groupBoxDlugoscZakladki = QGroupBox(self.centralwidget) self.groupBoxDlugoscZakladki.setEnabled(True) self.groupBoxDlugoscZakladki.setGeometry(QRect(210, 20, 131, 111)) self.groupBoxDlugoscZakladki.setTitle("Długość zakładki:") self.comboBoxDlugoscZakladki = QComboBox(self.groupBoxDlugoscZakladki) self.comboBoxDlugoscZakladki.setGeometry(QRect(10, 30, 70, 25)) self.comboBoxDlugoscZakladki.addItem("10%") self.comboBoxDlugoscZakladki.addItem("20%") self.comboBoxDlugoscZakladki.addItem("30%") self.comboBoxDlugoscZakladki.addItem("40%") self.comboBoxDlugoscZakladki.addItem("50%") self.comboBoxDlugoscZakladki.addItem("60%") self.comboBoxDlugoscZakladki.addItem("70%") self.comboBoxDlugoscZakladki.addItem("80%") self.comboBoxDlugoscZakladki.addItem("90%") self.comboBoxDlugoscZakladki.setCurrentIndex(3) self.comboBoxDlugoscZakladki.currentIndexChanged.connect( self.updateSpectrum) self.groupBoxOkno = QGroupBox(self.centralwidget) self.groupBoxOkno.setEnabled(True) self.groupBoxOkno.setGeometry(QRect(530, 20, 131, 111)) self.groupBoxOkno.setTitle("Okna:") self.comboBoxOkno = QComboBox(self.groupBoxOkno) self.comboBoxOkno.setEnabled(True) self.comboBoxOkno.setGeometry(QRect(10, 30, 81, 25)) self.comboBoxOkno.addItem("HAMMING") self.comboBoxOkno.addItem("BLACKMAN") self.comboBoxOkno.addItem("HANN") self.comboBoxOkno.addItem("BARTLETT") self.comboBoxOkno.addItem("TRIANG") self.comboBoxOkno.currentIndexChanged.connect(self.updateSpectrum) self.groupBoxDlugoscProbki = QGroupBox(self.centralwidget) self.groupBoxDlugoscProbki.setGeometry(QRect(370, 20, 131, 111)) self.groupBoxDlugoscProbki.setTitle("Dlugość próbki:") self.comboBoxDlugoscProbki = QComboBox(self.groupBoxDlugoscProbki) self.comboBoxDlugoscProbki.setGeometry(QRect(10, 30, 70, 25)) self.comboBoxDlugoscProbki.addItem("16") self.comboBoxDlugoscProbki.addItem("32") self.comboBoxDlugoscProbki.addItem("64") self.comboBoxDlugoscProbki.addItem("128") self.comboBoxDlugoscProbki.addItem("256") self.comboBoxDlugoscProbki.addItem("512") self.comboBoxDlugoscProbki.addItem("1024") self.comboBoxDlugoscProbki.addItem("2048") self.comboBoxDlugoscProbki.addItem("4096") self.comboBoxDlugoscProbki.setCurrentIndex(5) self.comboBoxDlugoscProbki.currentIndexChanged.connect( self.updateSpectrum) pg.setConfigOption('background', 'w') pg.setConfigOption('foreground', 'k') self.verticalLayout = QVBoxLayout(self.centralwidget) self.verticalLayout.setContentsMargins(12, 130, 10, 10) self.plotCalosc = pg.PlotWidget() self.plotCalosc.setTitle("FALA SYGNAŁU") self.plotCalosc.setLabel('bottom', "Czas", units='s') self.plotCalosc.setLabel('left', "Amplituda", units='') self.verticalLayout.addWidget(self.plotCalosc) self.plotFragment = pg.PlotWidget() self.plotFragment.setTitle("POWIEKSZONY FRAGMENT FALI SYGNAŁU") self.plotFragment.setLabel('bottom', "Czas", units='s') self.plotFragment.setLabel('left', "Amplituda", units='') self.verticalLayout.addWidget(self.plotFragment) self.plotSonogram = pg.PlotWidget() self.plotSonogram.setTitle("SPEKTOGRAM") self.plotSonogram.setLabel('bottom', "Czas", units='s') self.plotSonogram.setLabel('left', "Czestotliwosc", units='') self.verticalLayout.addWidget(self.plotSonogram) MainWindow.setCentralWidget(self.centralwidget) app.aboutToQuit.connect(self.closeEvent) def fileName(self): wave = QFileDialog.getOpenFileName( caption='Wczytaj dzwiek', filter="Music(*.wav)", options=QFileDialog.DontUseNativeDialog) if wave == ('', ''): QMessageBox.information(None, 'Informacja', "Nie wczytales dzwieku.", QMessageBox.Ok) else: self.nameFileWave = "" self.nameFileWave = wave[0] self.fileReadSound() def filePlay(self): print("Play") try: if self.nameFileWave == "": QMessageBox.information(None, 'Informacja', 'Nie został wczytany żaden dźwięk.', QMessageBox.Ok) else: if self.radioButtonCalosc.isChecked(): if self.pause == False: pygame.mixer.music.load(self.nameFileWave) pygame.mixer.music.play() else: pygame.mixer.music.unpause() self.pause = False else: if self.regionPause == False: try: pygame.mixer.music.load(self.nameFileWave) wavfile.write('fragment.wav', self.tempRegionRate, self.tempRegionData) except: pass pygame.mixer.music.load('fragment.wav') pygame.mixer.music.play() else: pygame.mixer.music.unpause() self.regionPause = False except: QMessageBox.information( None, 'Informacja', 'Program nie moze otworzyc dzwieku, ale przeanalizował sygnal.', QMessageBox.Ok) def filePause(self): print("Pause") try: if self.nameFileWave == "": QMessageBox.information(None, 'Informacja', 'Nie został wczytany żaden dźwięk.', QMessageBox.Ok) else: pygame.mixer.music.pause() if pygame.mixer.music.get_busy() == 0: self.pause = False self.regionPause = False else: self.pause = True self.regionPause = True except: pass def fileStop(self): print("Stop") try: if self.nameFileWave == "": QMessageBox.information(None, 'Informacja', 'Nie został wczytany żaden dźwięk.', QMessageBox.Ok) else: pygame.mixer.music.stop() self.pause = False self.regionPause = False except: pass def fileReadSound(self): try: self.pause = False self.regionPause = False rate, data = wavfile.read(self.nameFileWave) if len(data.shape) == 2: data = data[:, 1] try: pygame.mixer.music.load(self.nameFileWave) wavfile.write('fragment.wav', rate, data) except: QMessageBox.information( None, 'Informacja', 'Pliki wav nie moga miec polskich znakow.', QMessageBox.Ok) self.tempRegionRate = rate self.tempRegionData = data times = np.arange(len(data)) / float(rate) self.x = times self.y = data self.tempx = times self.tempy = data self.makePlot() except ValueError: self.nameFileWave = '' QMessageBox.information( None, 'Błąd', 'Nie można wczytać tego pliku,\n Proszę wybrać inny.', QMessageBox.Ok) def makePlot(self): if self.deletePlotFragment: self.plotFragment.close() self.plotCalosc.plot(x=self.x, y=self.y, clear=True) tempMinX = min(self.x) tempMaxX = max(self.x) tempMinY = min(self.y) tempMaxY = max(self.y) tempDistanceX = 0.02 if tempMaxX <= 10.0: pass else: if tempMaxX <= 100.0: tempDistanceX = 0.2 else: tempDistanceX = 2.0 if tempMinY > 0: tempDistanceMinY = tempMinY - tempMinY / 2 else: if tempMinY < 0: tempDistanceMinY = tempMinY + tempMinY / 2 else: tempDistanceMinY = -10 if tempMaxY < 0: tempDistanceMaxY = tempMaxX - tempMaxX / 2 else: if tempMaxY > 0: tempDistanceMaxY = tempMaxY + tempMaxY / 2 else: tempDistanceMaxY = +10 self.plotCalosc.setRange( xRange=[tempMinX - tempDistanceX, tempMaxX + tempDistanceX], yRange=[tempDistanceMinY, tempDistanceMaxY]) self.plotCalosc.setLimits(xMin=tempMinX - tempDistanceX, xMax=tempMaxX + tempDistanceX, yMin=tempDistanceMinY, yMax=tempDistanceMaxY) if (max(self.x) < 90.0): self.region = pg.LinearRegionItem([0, self.x[-1]], bounds=[0, self.x[-1]]) self.region.setZValue(100) self.plotCalosc.addItem(self.region) self.region.sigRegionChanged.connect(self.updateRegion) self.plotFragment = pg.PlotWidget(x=self.tempx, y=self.tempy) self.plotFragment.setRange( xRange=[tempMinX - tempDistanceX, tempMaxX + tempDistanceX], yRange=[tempDistanceMinY, tempDistanceMaxY]) self.plotFragment.setLimits(xMin=tempMinX - tempDistanceX, xMax=tempMaxX + tempDistanceX, yMin=tempDistanceMinY, yMax=tempDistanceMaxY) self.plotFragment.setTitle("POWIEKSZONY FRAGMENT FALI SYGNAŁU") self.plotFragment.setLabel('bottom', "Czas", units='s') self.plotFragment.setLabel('left', "Amplituda", units='') self.verticalLayout.addWidget(self.plotFragment) self.deletePlotFragment = True else: self.deletePlotFragment = False self.makeSpectrum() def updateRegion(self): temp = (self.x > self.region.getRegion()[0] - 0.000000001) & ( self.x < self.region.getRegion()[1] + 0.000000001) self.tempx = self.x[temp] self.tempy = self.y[temp] self.tempRegionData = self.tempy self.updatePlot() def updatePlot(self): self.regionPause = False tempMinX = min(self.tempx) tempMaxX = max(self.tempx) tempMinY = min(self.tempy) tempMaxY = max(self.tempy) if tempMinY > 0: tempDistanceMinY = tempMinY - tempMinY / 2 else: if tempMinY < 0: tempDistanceMinY = tempMinY + tempMinY / 2 else: tempDistanceMinY = -10 if tempMaxY < 0: tempDistanceMaxY = tempMaxX - tempMaxX / 2 else: if tempMaxY > 0: tempDistanceMaxY = tempMaxY + tempMaxY / 2 else: tempDistanceMaxY = +10 self.plotFragment.setRange(xRange=[tempMinX, tempMaxX], yRange=[tempDistanceMinY, tempDistanceMaxY]) self.plotFragment.setLimits(xMin=tempMinX, xMax=tempMaxX, yMin=tempDistanceMinY, yMax=tempDistanceMaxY) self.plotFragment.plot(x=self.tempx, y=self.tempy, clear=True) self.updateSpectrum() def makeSpectrum(self): if self.nameFileWave == "": overlap = self.dlugoscZakladki( self.comboBoxDlugoscZakladki.currentText()) window = self.comboBoxOkno.currentText().lower() nperseg = int(self.comboBoxDlugoscProbki.currentText()) else: overlap = self.dlugoscZakladki( self.comboBoxDlugoscZakladki.currentText()) window = self.comboBoxOkno.currentText().lower() nperseg = int(self.comboBoxDlugoscProbki.currentText()) tempwindow = get_window(window, nperseg) tempoverlap = nperseg * overlap tempoverlap = int(round(tempoverlap)) try: f, t, S = self.stft(self.tempy, self.tempRegionRate, tempwindow, nperseg, tempoverlap, window) S = 20 * np.log10(S) self.plotSonogram.close() self.plotSonogram = pg.PlotWidget() self.plotSonogram.setTitle("SPEKTOGRAM") self.plotSonogram.setLabel('bottom', "Czas", units='s') self.plotSonogram.setLabel('left', "Czestotliwosc", units='Hz') pg.setConfigOptions(imageAxisOrder='row-major') self.img = pg.ImageItem() self.plotSonogram.addItem(self.img) hist = pg.HistogramLUTItem() hist.setImageItem(self.img) hist.setLevels(np.min(S), np.max(S)) hist.gradient.restoreState({ 'mode': 'rgb', 'ticks': [(0.0, (0, 255, 255, 255)), (0.25, (0, 0, 255, 255)), (0.5, (0, 0, 0, 255)), (0.75, (255, 0, 0, 255)), (1.0, (255, 255, 0, 255))] }) self.img.setImage(S) self.img.scale(t[-1] / np.size(S, axis=1), f[-1] / np.size(S, axis=0)) self.plotSonogram.setLimits(xMin=0, xMax=t[-1], yMin=0, yMax=f[-1]) self.verticalLayout.addWidget(self.plotSonogram) except: pass def updateSpectrum(self): overlap = self.dlugoscZakladki( self.comboBoxDlugoscZakladki.currentText()) window = self.comboBoxOkno.currentText().lower() nperseg = int(self.comboBoxDlugoscProbki.currentText()) tempwindow = get_window(window, nperseg) tempoverlap = nperseg * overlap tempoverlap = int(round(tempoverlap)) try: f, t, S = self.stft(self.tempy, self.tempRegionRate, tempwindow, nperseg, tempoverlap, window) S = 20 * np.log10(S) pg.setConfigOptions(imageAxisOrder='row-major') self.img = pg.ImageItem() self.plotSonogram.plot(clear=True) self.plotSonogram.addItem(self.img) hist = pg.HistogramLUTItem() hist.setImageItem(self.img) hist.setLevels(np.min(S), np.max(S)) hist.gradient.restoreState({ 'mode': 'rgb', 'ticks': [(0.0, (0, 255, 255, 255)), (1.0, (255, 255, 0, 255)), (0.5, (0, 0, 0, 255)), (0.25, (0, 0, 255, 255)), (0.75, (255, 0, 0, 255))] }) self.img.setImage(S) self.img.scale(t[-1] / np.size(S, axis=1), f[-1] / np.size(S, axis=0)) self.plotSonogram.setLimits(xMin=0, xMax=t[-1], yMin=0, yMax=f[-1]) except: pass def stft(self, x, fs, window, nperseg, noverlap, nameWindow): x = np.asarray(x) outdtype = np.result_type(x, np.complex64) if x.size == 0: return np.empty(x.shape), np.empty(x.shape), np.empty(x.shape) if nperseg > x.shape[-1]: nperseg = x.shape[-1] win = get_window(nameWindow, nperseg) else: win = window if np.result_type(win, np.complex64) != outdtype: win = win.astype(outdtype) scale = 1.0 / win.sum()**2 scale = np.sqrt(scale) if np.iscomplexobj(x): freqs = fftpack.fftfreq(nperseg, 1 / fs) else: freqs = np.fft.rfftfreq(nperseg, 1 / fs) result = self.fft(x, win, nperseg, noverlap) result *= scale time = np.arange(nperseg / 2, x.shape[-1] - nperseg / 2 + 1, nperseg - noverlap) / float(fs) result = result.astype(outdtype) result = np.rollaxis(result, -1, -2) result = np.abs(result) tempResult = result[result != 0] result[result == 0] = np.min(tempResult) return freqs, time, result def fft(self, x, win, nperseg, noverlap): if nperseg == 1 and noverlap == 0: result = x[..., np.newaxis] else: step = nperseg - noverlap shape = x.shape[:-1] + ((x.shape[-1] - noverlap) // step, nperseg) strides = x.strides[:-1] + (step * x.strides[-1], x.strides[-1]) result = np.lib.stride_tricks.as_strided(x, shape=shape, strides=strides) result = signaltools.detrend(result, type='constant', axis=-1) result = win * result if np.iscomplexobj(x): func = fftpack.fft else: result = result.real func = np.fft.rfft result = func(result, n=nperseg) return result def dlugoscZakladki(self, temp): if (temp == '10%'): overlap = 0.1 else: if (temp == '20%'): overlap = 0.2 else: if (temp == '30%'): overlap = 0.3 else: if (temp == '40%'): overlap = 0.4 else: if (temp == '50%'): overlap = 0.5 else: if (temp == '60%'): overlap = 0.6 else: if (temp == '70%'): overlap = 0.7 else: if (temp == '80%'): overlap = 0.8 else: overlap = 0.9 return overlap def closeEvent(self): if os.path.isfile('fragment.wav'): pygame.mixer.quit() os.remove('fragment.wav')
class Florodoro(QWidget): def parseArguments(self): parser = argparse.ArgumentParser( description="A pomodoro timer that grows procedurally generated trees and flowers while you're studying.", ) parser.add_argument( "-d", "--debug", action="store_true", help="run the app in debug mode", ) return parser.parse_args() def __init__(self): super().__init__() arguments = self.parseArguments() self.DEBUG = arguments.debug os.chdir(os.path.dirname(os.path.realpath(__file__))) self.MIN_WIDTH = 600 self.MIN_HEIGHT = 350 self.setMinimumWidth(self.MIN_WIDTH) self.setMinimumHeight(self.MIN_HEIGHT) self.ROOT_FOLDER = os.path.expanduser("~/.florodoro/") self.HISTORY_FILE_PATH = self.ROOT_FOLDER + "history" + ("" if not self.DEBUG else "-debug") + ".yaml" self.CONFIGURATION_FILE_PATH = self.ROOT_FOLDER + "config" + ("" if not self.DEBUG else "-debug") + ".yaml" self.history = History(self.HISTORY_FILE_PATH) self.SOUNDS_FOLDER = "sounds/" self.PLANTS_FOLDER = "plants/" self.IMAGE_FOLDER = "images/" self.TEXT_COLOR = self.palette().text().color() self.BREAK_COLOR = "#B37700" self.APP_NAME = "Florodoro" self.STUDY_ICON = qtawesome.icon('fa5s.book', color=self.TEXT_COLOR) self.BREAK_ICON = qtawesome.icon('fa5s.coffee', color=self.BREAK_COLOR) self.CONTINUE_ICON = qtawesome.icon('fa5s.play', color=self.TEXT_COLOR) self.PAUSE_ICON = qtawesome.icon('fa5s.pause', color=self.TEXT_COLOR) self.RESET_ICON = qtawesome.icon('fa5s.undo', color=self.TEXT_COLOR) self.PLANTS = [GreenTree, DoubleGreenTree, OrangeTree, CircularFlower] self.PLANT_NAMES = ["Spruce", "Double spruce", "Maple", "Flower"] self.MAX_PLANT_AGE = 90 # maximum number of minutes to make the plant optimal in size self.WIDGET_SPACING = 10 self.MAX_TIME = 180 self.STEP = 5 self.INITIAL_TEXT = "Start!" self.menuBar = QMenuBar(self) self.presets_menu = self.menuBar.addMenu('&Presets') self.presets = { "Classic": (25, 5, 4), "Extended": (45, 12, 2), "Sitcomodoro": (65, 25, 1), } for name in self.presets: study_time, break_time, cycles = self.presets[name] self.presets_menu.addAction( QAction(f"{name} ({study_time} : {break_time} : {cycles})", self, triggered=partial(self.load_preset, study_time, break_time, cycles))) self.DEFAULT_PRESET = "Classic" self.options_menu = self.menuBar.addMenu('&Options') self.notify_menu = self.options_menu.addMenu("&Notify") self.sound_action = QAction("&Sound", self, checkable=True, checked=not self.DEBUG, triggered=lambda _: self.volume_slider.setDisabled( not self.sound_action.isChecked())) self.notify_menu.addAction(self.sound_action) self.volume_slider = QSlider(Qt.Horizontal, minimum=0, maximum=100, value=85) slider_action = QWidgetAction(self) slider_action.setDefaultWidget(SpacedQWidget(self.volume_slider)) self.notify_menu.addAction(slider_action) self.popup_action = QAction("&Pop-up", self, checkable=True, checked=True) self.notify_menu.addAction(self.popup_action) self.menuBar.addAction( QAction( "&Statistics", self, triggered=lambda: self.statistics.show() if self.statistics.isHidden() else self.statistics.hide() ) ) self.menuBar.addAction( QAction( "&About", self, triggered=lambda: QMessageBox.information( self, "About", "This application was created by Tomáš Sláma. It is heavily inspired by the Android app Forest, " "but with all of the plants generated procedurally. It's <a href='https://github.com/xiaoxiae/Florodoro'>open source</a> and licensed " "under MIT, so do as you please with the code and anything else related to the project.", ), ) ) self.plant_menu = self.options_menu.addMenu("&Plants") self.overstudy_action = QAction("Overstudy", self, checkable=True) self.options_menu.addAction(self.overstudy_action) self.plant_images = [] self.plant_checkboxes = [] # dynamically create widgets for each plant for plant, name in zip(self.PLANTS, self.PLANT_NAMES): self.plant_images.append(tempfile.NamedTemporaryFile(suffix=".svg")) tmp = plant() tmp.set_max_age(1) tmp.set_age(1) tmp.save(self.plant_images[-1].name, 200, 200) setattr(self.__class__, name, QAction(self, icon=QIcon(self.plant_images[-1].name), text=name, checkable=True, checked=True)) action = getattr(self.__class__, name) self.plant_menu.addAction(action) self.plant_checkboxes.append(action) # the current plant that we're growing # if set to none, no plant is growing self.plant = None self.menuBar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) main_vertical_layout = QVBoxLayout(self) main_vertical_layout.setContentsMargins(0, 0, 0, 0) main_vertical_layout.setSpacing(0) main_vertical_layout.addWidget(self.menuBar) self.canvas = Canvas(self) self.statistics = Statistics(self.history) font = self.font() font.setPointSize(100) self.main_label = QLabel(self, alignment=Qt.AlignCenter) self.main_label.setFont(font) self.main_label.setText(self.INITIAL_TEXT) font.setPointSize(26) self.cycle_label = QLabel(self) self.cycle_label.setAlignment(Qt.AlignTop) self.cycle_label.setMargin(20) self.cycle_label.setFont(font) main_horizontal_layout = QHBoxLayout(self) self.study_time_spinbox = QSpinBox(self, prefix="Study for: ", suffix="min.", minimum=1, maximum=self.MAX_TIME, singleStep=self.STEP) self.break_time_spinbox = QSpinBox(self, prefix="Break for: ", suffix="min.", minimum=1, maximum=self.MAX_TIME, singleStep=self.STEP, styleSheet=f'color:{self.BREAK_COLOR};') self.cycles_spinbox = QSpinBox(self, prefix="Cycles: ", minimum=1, value=1) # keep track of remaining number of cycles and the starting number of cycles self.remaining_cycles = 0 self.total_cycles = 0 # whether we're currently studying self.is_study_ongoing = False # whether we notified the user already during overstudy self.already_notified_during_overstudy = False stacked_layout = QStackedLayout(self, stackingMode=QStackedLayout.StackAll) stacked_layout.addWidget(self.main_label) stacked_layout.addWidget(self.cycle_label) stacked_layout.addWidget(self.canvas) main_vertical_layout.addLayout(stacked_layout) self.setStyleSheet("") self.study_button = QPushButton(self, clicked=self.start, icon=self.STUDY_ICON) self.break_button = QPushButton(self, clicked=self.start_break, icon=self.BREAK_ICON) self.pause_button = QPushButton(self, clicked=self.toggle_pause, icon=self.PAUSE_ICON) self.reset_button = QPushButton(self, clicked=self.reset, icon=self.RESET_ICON) main_horizontal_layout.addWidget(self.study_time_spinbox) main_horizontal_layout.addWidget(self.break_time_spinbox) main_horizontal_layout.addWidget(self.cycles_spinbox) main_horizontal_layout.addWidget(self.study_button) main_horizontal_layout.addWidget(self.break_button) main_horizontal_layout.addWidget(self.pause_button) main_horizontal_layout.addWidget(self.reset_button) main_vertical_layout.addLayout(main_horizontal_layout) self.setLayout(main_vertical_layout) self.study_timer_frequency = 1 / 60 * 1000 self.study_timer = QTimer(self, interval=int(self.study_timer_frequency), timeout=self.decrease_remaining_time) self.player = QMediaPlayer(self) self.setWindowIcon(QIcon(self.IMAGE_FOLDER + "icon.svg")) self.setWindowTitle(self.APP_NAME) # set initial UI state self.reset() # a list of name, getter and setter things to load/save when the app opens/closes # also dynamically get settings for selecting/unselecting plants self.CONFIGURATION_ATTRIBUTES = [("study-time", self.study_time_spinbox.value, self.study_time_spinbox.setValue), ("break-time", self.break_time_spinbox.value, self.break_time_spinbox.setValue), ("cycles", self.cycles_spinbox.value, self.cycles_spinbox.setValue), ("sound", self.sound_action.isChecked, self.sound_action.setChecked), ("sound-volume", self.volume_slider.value, self.volume_slider.setValue), ("pop-ups", self.popup_action.isChecked, self.popup_action.setChecked), ("overstudy", self.overstudy_action.isChecked, self.overstudy_action.setChecked)] + \ [(name.lower(), getattr(self.__class__, name).isChecked, getattr(self.__class__, name).setChecked) for _, name in zip(self.PLANTS, self.PLANT_NAMES)] # load the default preset self.load_preset(*self.presets[self.DEFAULT_PRESET]) self.load_settings() self.show() def load_settings(self): """Loads the settings file (if it exists).""" if os.path.exists(self.CONFIGURATION_FILE_PATH): with open(self.CONFIGURATION_FILE_PATH) as file: configuration = yaml.load(file, Loader=yaml.FullLoader) # don't crash if config is broken if not isinstance(configuration, dict): return for key in configuration: for name, _, setter in self.CONFIGURATION_ATTRIBUTES: if key == name: setter(configuration[key]) def save_settings(self): """Saves the settings file (if it exists).""" if not os.path.exists(self.ROOT_FOLDER): os.mkdir(self.ROOT_FOLDER) with open(self.CONFIGURATION_FILE_PATH, 'w') as file: configuration = {} for name, getter, _ in self.CONFIGURATION_ATTRIBUTES: configuration[name] = getter() file.write(yaml.dump(configuration)) def closeEvent(self, event): """Called when the app is being closed. Overridden to also save Florodoro settings.""" self.save_settings() super().closeEvent(event) def load_preset(self, study_value: int, break_value: int, cycles: int): """Load a pomodoro preset.""" self.study_time_spinbox.setValue(study_value) self.break_time_spinbox.setValue(break_value) self.cycles_spinbox.setValue(cycles) def keyPressEvent(self, event: QKeyEvent) -> None: """Debug-related keyboard controls.""" if self.DEBUG: if event.key() == Qt.Key_Escape: possible_plants = [plant for i, plant in enumerate(self.PLANTS) if self.plant_checkboxes[i].isChecked()] if len(possible_plants) != 0: self.plant = choice(possible_plants)() self.canvas.set_drawable(self.plant) self.plant.set_max_age(1) self.plant.set_age(1) self.canvas.update() def start_break(self): """Starts the break, instead of the study.""" # if we're overstudying, this can be pressed when studying, so save that we did so if self.overstudy_action.isChecked() and self.is_study_ongoing: self.save_study(ignore_remainder=False) self.start(do_break=True) def start(self, do_break=False): """The function for starting either the study or break timer (depending on do_break).""" self.study_button.setEnabled(do_break) self.break_button.setEnabled(self.overstudy_action.isChecked() and not do_break) self.reset_button.setDisabled(False) self.pause_button.setDisabled(False) self.pause_button.setIcon(self.PAUSE_ICON) # if we're initially starting to do cycles, reset their count # don't reset on break, because we could be doing a standalone break if self.remaining_cycles == 0 and not do_break: self.remaining_cycles = self.cycles_spinbox.value() self.total_cycles = self.remaining_cycles else: # if we're not studing and are about to when there is still leftover time, we're ending the break quicker than intended # therefore, reduce cycles by 1, since they would have been if the timer were to run out during break if not self.is_study_ongoing and not do_break and self.get_leftover_time() / self.total_time > 0: self.remaining_cycles -= 1 if self.remaining_cycles == 0: self.reset() return # set depending on whether we are currently studying or not self.is_study_ongoing = not do_break self.already_notified_during_overstudy = False self.main_label.setStyleSheet('' if not do_break else f'color:{self.BREAK_COLOR};') # the total time to study for (spinboxes are minutes) # since it's rounded down and it looks better to start at the exact time, 0.99 is added self.total_time = (self.study_time_spinbox if not do_break else self.break_time_spinbox).value() * 60 + 0.99 self.ending_time = datetime.now() + timedelta(minutes=self.total_time / 60) # so it's displayed immediately self.update_time_label(self.total_time) self.update_cycles_label() # don't start showing canvas and growing the plant when we're not studying if not do_break: possible_plants = [plant for i, plant in enumerate(self.PLANTS) if self.plant_checkboxes[i].isChecked()] if len(possible_plants) != 0: self.plant = choice(possible_plants)() self.canvas.set_drawable(self.plant) self.plant.set_max_age(min(1, (self.total_time / 60) / self.MAX_PLANT_AGE)) self.plant.set_age(0) else: self.plant = None self.study_timer.stop() # it could be running - we could be currently in a break self.study_timer.start() def toggle_pause(self): """Called when the pause button is pressed. Either stops the timer or starts it again, while also doing stuff to the pause icons.""" # stop the timer, if it's running if self.study_timer.isActive(): self.study_timer.stop() self.pause_button.setIcon(self.CONTINUE_ICON) self.pause_time = datetime.now() # if not, resume else: self.ending_time += datetime.now() - self.pause_time self.study_timer.start() self.pause_button.setIcon(self.PAUSE_ICON) def reset(self): """Reset the UI.""" self.study_timer.stop() self.pause_button.setIcon(self.PAUSE_ICON) self.main_label.setStyleSheet('') self.study_button.setDisabled(False) self.break_button.setDisabled(False) self.pause_button.setDisabled(True) self.reset_button.setDisabled(True) if self.plant is not None: self.plant.set_age(0) self.remaining_cycles = 0 self.main_label.setText(self.INITIAL_TEXT) self.cycle_label.setText('') def update_time_label(self, time): """Update the text of the time label, given some time in seconds.""" sign = -1 if time < 0 else 1 time = abs(time) hours = int(time // 3600) minutes = int((time // 60) % 60) seconds = int(time % 60) # smooth timer: hide minutes/hours if there are none result = "-" if sign == -1 else "" if hours == 0: if minutes == 0: result += str(seconds) else: result += str(minutes) + QTime(0, 0, seconds).toString(":ss") else: result += str(hours) + QTime(0, minutes, seconds).toString(":mm:ss") self.main_label.setText(result) def play_sound(self, name: str): """Play a file from the sound directory. Extension is not included, will be added automatically.""" for file in os.listdir(self.SOUNDS_FOLDER): # if the file starts with the provided name and only contains an extension after, try to play it if file.startswith(name) and file[len(name):][0] == ".": path = QDir.current().absoluteFilePath(self.SOUNDS_FOLDER + file) url = QUrl.fromLocalFile(path) content = QMediaContent(url) self.player.setMedia(content) self.player.setVolume(self.volume_slider.value()) self.player.play() def show_notification(self, message: str): """Show the specified notification using plyer.""" notification.notify(self.APP_NAME, message, self.APP_NAME, os.path.abspath(self.IMAGE_FOLDER + "icon.svg")) def update_cycles_label(self): """Update the cycles label, if we're currently studying and it wouldn't be 1/1.""" if self.total_cycles != 1 and self.is_study_ongoing: self.cycle_label.setText(f"{self.total_cycles - self.remaining_cycles + 1}/{self.total_cycles}") def get_leftover_time(self): """Return time until the timer runs out.""" return (self.ending_time - datetime.now()).total_seconds() def decrease_remaining_time(self): """Decrease the remaining time by the timer frequency. Updates clock/plant growth.""" if self.DEBUG: self.ending_time -= timedelta(seconds=30) self.update_time_label(self.get_leftover_time()) if self.get_leftover_time() <= 0: if self.is_study_ongoing: # only notify once per study, since this would be called all the time during overstudy if not self.already_notified_during_overstudy: if self.sound_action.isChecked(): self.play_sound("study_done") if self.popup_action.isChecked(): self.show_notification("Studying finished, take a break!") self.already_notified_during_overstudy = True if not self.overstudy_action.isChecked(): self.save_study() # save before break! self.start_break() else: self.history.add_break(datetime.now(), self.total_time // 60) self.statistics.refresh() if self.sound_action.isChecked(): self.play_sound("break_done") if self.popup_action.isChecked(): self.show_notification("Break is over!") self.remaining_cycles -= 1 if self.remaining_cycles <= 0: # <=, because we could have just started a simple break self.reset() else: self.start() self.update_cycles_label() else: # if there is leftover time and we haven't finished studying, grow the plant if self.is_study_ongoing: if self.plant is not None: self.plant.set_age(1 - (self.get_leftover_time() / self.total_time)) self.canvas.update() def save_study(self, ignore_remainder=True): """Save the record of the current study to the history file. By default, ignore the leftover time, since it will be a tiny number.""" date = datetime.now() duration = (self.total_time - self.get_leftover_time()) / 60 if ignore_remainder: duration = float(int(duration)) self.history.add_study(date, duration, self.plant) self.statistics.move() # move to the last plant self.statistics.refresh()
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) MainWindow.resize(1010, 754) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName( _fromUtf8("centralwidget")) # do not change this name self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.splitter_2 = QSplitter(self.centralwidget) self.splitter_2.setOrientation(Qt.Vertical) self.splitter_2.setObjectName(_fromUtf8("splitter_2")) self.MainTabWidget = QTabWidget(self.splitter_2) self.MainTabWidget.setObjectName(_fromUtf8("MainTabWidget")) self.ScanTab = QWidget() self.ScanTab.setObjectName(_fromUtf8("ScanTab")) self.gridLayout_2 = QGridLayout(self.ScanTab) self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) self.splitter = QSplitter(self.ScanTab) self.splitter.setOrientation(Qt.Horizontal) self.splitter.setObjectName(_fromUtf8("splitter")) # size policies self.sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.sizePolicy.setHorizontalStretch( 0 ) # this specifies that the widget will keep its width when the window is resized self.sizePolicy.setVerticalStretch(0) self.sizePolicy2 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.sizePolicy2.setHorizontalStretch( 1 ) # this specifies that the widget will expand its width when the window is resized self.sizePolicy2.setVerticalStretch(0) self.setupLeftPanel() self.setupRightPanel() self.setupMainTabs() self.setupBottomPanel() self.gridLayout.addWidget(self.splitter_2, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.setupMenuBar(MainWindow) self.retranslateUi(MainWindow) self.setDefaultIndexes() QMetaObject.connectSlotsByName(MainWindow) def setupLeftPanel(self): self.HostsTabWidget = QTabWidget(self.splitter) self.sizePolicy.setHeightForWidth( self.HostsTabWidget.sizePolicy().hasHeightForWidth()) self.HostsTabWidget.setSizePolicy(self.sizePolicy) self.HostsTabWidget.setObjectName(_fromUtf8("HostsTabWidget")) self.HostsTab = QWidget() self.HostsTab.setObjectName(_fromUtf8("HostsTab")) self.keywordTextInput = QLineEdit() self.FilterApplyButton = QToolButton() self.searchIcon = QIcon() self.searchIcon.addPixmap(QPixmap(_fromUtf8("./images/search.png")), QIcon.Normal, QIcon.Off) self.FilterApplyButton.setIconSize(QSize(29, 21)) self.FilterApplyButton.setIcon(self.searchIcon) self.FilterAdvancedButton = QToolButton() self.advancedIcon = QIcon() self.advancedIcon.addPixmap( QPixmap(_fromUtf8("./images/advanced.png")), QIcon.Normal, QIcon.Off) self.FilterAdvancedButton.setIconSize(QSize(19, 19)) self.FilterAdvancedButton.setIcon(self.advancedIcon) self.vlayout = QVBoxLayout(self.HostsTab) self.vlayout.setObjectName(_fromUtf8("vlayout")) self.HostsTableView = QTableView(self.HostsTab) self.HostsTableView.setObjectName(_fromUtf8("HostsTableView")) self.vlayout.addWidget(self.HostsTableView) self.addHostsOverlay = QTextEdit( self.HostsTab ) # the overlay widget that appears over the hosttableview self.addHostsOverlay.setObjectName(_fromUtf8("addHostsOverlay")) self.addHostsOverlay.setText('Click here to add host(s) to scope') self.addHostsOverlay.setReadOnly(True) self.addHostsOverlay.setContextMenuPolicy(Qt.NoContextMenu) ### self.addHostsOverlay.setFont(QFont('', 12)) self.addHostsOverlay.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) ### self.vlayout.addWidget(self.addHostsOverlay) self.hlayout = QHBoxLayout() self.hlayout.addWidget(self.keywordTextInput) self.hlayout.addWidget(self.FilterApplyButton) self.hlayout.addWidget(self.FilterAdvancedButton) self.vlayout.addLayout(self.hlayout) self.HostsTabWidget.addTab(self.HostsTab, _fromUtf8("")) self.ServicesLeftTab = QWidget() self.ServicesLeftTab.setObjectName(_fromUtf8("ServicesLeftTab")) self.horizontalLayout_2 = QHBoxLayout(self.ServicesLeftTab) self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2")) self.ServiceNamesTableView = QTableView(self.ServicesLeftTab) self.ServiceNamesTableView.setObjectName( _fromUtf8("ServiceNamesTableView")) self.horizontalLayout_2.addWidget(self.ServiceNamesTableView) self.HostsTabWidget.addTab(self.ServicesLeftTab, _fromUtf8("")) self.ToolsTab = QWidget() self.ToolsTab.setObjectName(_fromUtf8("ToolsTab")) self.horizontalLayout_3 = QHBoxLayout(self.ToolsTab) self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3")) self.ToolsTableView = QTableView(self.ToolsTab) self.ToolsTableView.setObjectName(_fromUtf8("ToolsTableView")) self.horizontalLayout_3.addWidget(self.ToolsTableView) self.HostsTabWidget.addTab(self.ToolsTab, _fromUtf8("")) def setupRightPanel(self): self.ServicesTabWidget = QTabWidget() self.ServicesTabWidget.setEnabled(True) self.sizePolicy2.setHeightForWidth( self.ServicesTabWidget.sizePolicy().hasHeightForWidth()) self.ServicesTabWidget.setSizePolicy(self.sizePolicy2) self.ServicesTabWidget.setObjectName(_fromUtf8("ServicesTabWidget")) self.splitter.addWidget(self.ServicesTabWidget) ### self.splitter_3 = QSplitter() self.splitter_3.setOrientation(Qt.Horizontal) self.splitter_3.setObjectName(_fromUtf8("splitter_3")) self.splitter_3.setSizePolicy( self.sizePolicy2 ) # this makes the tools tab stay the same width when resizing the window ### self.ToolHostsWidget = QWidget() self.ToolHostsWidget.setObjectName(_fromUtf8("ToolHostsTab")) self.ToolHostsLayout = QVBoxLayout(self.ToolHostsWidget) self.ToolHostsLayout.setObjectName(_fromUtf8("verticalLayout")) self.ToolHostsTableView = QTableView(self.ToolHostsWidget) self.ToolHostsTableView.setObjectName(_fromUtf8("ServicesTableView")) self.ToolHostsLayout.addWidget(self.ToolHostsTableView) self.splitter_3.addWidget(self.ToolHostsWidget) self.DisplayWidget = QWidget() self.DisplayWidget.setObjectName('ToolOutput') self.DisplayWidget.setSizePolicy(self.sizePolicy2) #self.toolOutputTextView = QTextEdit(self.DisplayWidget) self.toolOutputTextView = QPlainTextEdit(self.DisplayWidget) self.toolOutputTextView.setReadOnly(True) self.DisplayWidgetLayout = QHBoxLayout(self.DisplayWidget) self.DisplayWidgetLayout.addWidget(self.toolOutputTextView) self.splitter_3.addWidget(self.DisplayWidget) self.ScreenshotWidget = ImageViewer() self.ScreenshotWidget.setObjectName('Screenshot') self.ScreenshotWidget.scrollArea.setSizePolicy(self.sizePolicy2) self.ScreenshotWidget.scrollArea.setContextMenuPolicy( Qt.CustomContextMenu) self.splitter_3.addWidget(self.ScreenshotWidget.scrollArea) self.splitter.addWidget(self.splitter_3) ### self.ServicesRightTab = QWidget() self.ServicesRightTab.setObjectName(_fromUtf8("ServicesRightTab")) self.verticalLayout = QVBoxLayout(self.ServicesRightTab) self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) self.ServicesTableView = QTableView(self.ServicesRightTab) self.ServicesTableView.setObjectName(_fromUtf8("ServicesTableView")) self.verticalLayout.addWidget(self.ServicesTableView) self.ServicesTabWidget.addTab(self.ServicesRightTab, _fromUtf8("")) self.ScriptsTab = QWidget() self.ScriptsTab.setObjectName(_fromUtf8("ScriptsTab")) self.horizontalLayout_6 = QHBoxLayout(self.ScriptsTab) self.horizontalLayout_6.setObjectName(_fromUtf8("horizontalLayout_6")) self.splitter_4 = QSplitter(self.ScriptsTab) self.splitter_4.setOrientation(Qt.Horizontal) self.splitter_4.setObjectName(_fromUtf8("splitter_4")) self.ScriptsTableView = QTableView() self.ScriptsTableView.setObjectName(_fromUtf8("ScriptsTableView")) self.splitter_4.addWidget(self.ScriptsTableView) self.ScriptsOutputTextEdit = QPlainTextEdit() self.ScriptsOutputTextEdit.setObjectName( _fromUtf8("ScriptsOutputTextEdit")) self.ScriptsOutputTextEdit.setReadOnly(True) self.splitter_4.addWidget(self.ScriptsOutputTextEdit) self.horizontalLayout_6.addWidget(self.splitter_4) self.ServicesTabWidget.addTab(self.ScriptsTab, _fromUtf8("")) self.InformationTab = QWidget() self.InformationTab.setObjectName(_fromUtf8("InformationTab")) self.ServicesTabWidget.addTab(self.InformationTab, _fromUtf8("")) self.NotesTab = QWidget() self.NotesTab.setObjectName(_fromUtf8("NotesTab")) self.horizontalLayout_4 = QHBoxLayout(self.NotesTab) self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4")) #self.NotesTextEdit = QTextEdit(self.NotesTab) self.NotesTextEdit = QPlainTextEdit(self.NotesTab) self.NotesTextEdit.setObjectName(_fromUtf8("NotesTextEdit")) self.horizontalLayout_4.addWidget(self.NotesTextEdit) self.ServicesTabWidget.addTab(self.NotesTab, _fromUtf8("")) def setupMainTabs(self): self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1) self.gridLayout_3 = QGridLayout() self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) self.gridLayout_2.addLayout(self.gridLayout_3, 0, 0, 1, 1) self.MainTabWidget.addTab(self.ScanTab, _fromUtf8("")) self.BruteTab = QWidget() self.BruteTab.setObjectName(_fromUtf8("BruteTab")) self.horizontalLayout_7 = QHBoxLayout(self.BruteTab) self.horizontalLayout_7.setObjectName(_fromUtf8("horizontalLayout_7")) self.BruteTabWidget = QTabWidget(self.BruteTab) self.BruteTabWidget.setObjectName(_fromUtf8("BruteTabWidget")) self.horizontalLayout_7.addWidget(self.BruteTabWidget) self.MainTabWidget.addTab(self.BruteTab, _fromUtf8("")) def setupBottomPanel(self): self.BottomTabWidget = QTabWidget(self.splitter_2) self.BottomTabWidget.setSizeIncrement(QSize(0, 0)) self.BottomTabWidget.setBaseSize(QSize(0, 0)) self.BottomTabWidget.setObjectName(_fromUtf8("BottomTabWidget")) self.LogTab = QWidget() self.LogTab.setObjectName(_fromUtf8("LogTab")) self.horizontalLayout_5 = QHBoxLayout(self.LogTab) self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5")) self.ProcessesTableView = QTableView(self.LogTab) self.ProcessesTableView.setObjectName(_fromUtf8("ProcessesTableView")) self.horizontalLayout_5.addWidget(self.ProcessesTableView) self.BottomTabWidget.addTab(self.LogTab, _fromUtf8("")) # self.TerminalTab = QWidget() # self.TerminalTab.setObjectName(_fromUtf8("TerminalTab")) # self.BottomTabWidget.addTab(self.TerminalTab, _fromUtf8("")) # self.PythonTab = QWidget() # self.PythonTab.setObjectName(_fromUtf8("PythonTab")) # self.BottomTabWidget.addTab(self.PythonTab, _fromUtf8("")) def setupMenuBar(self, MainWindow): self.menubar = QMenuBar(MainWindow) self.menubar.setGeometry(QRect(0, 0, 1010, 25)) self.menubar.setObjectName(_fromUtf8("menubar")) self.menuFile = QMenu(self.menubar) self.menuFile.setObjectName(_fromUtf8("menuFile")) # self.menuEdit = QMenu(self.menubar) # self.menuEdit.setObjectName(_fromUtf8("menuEdit")) # self.menuSettings = QMenu(self.menubar) # self.menuSettings.setObjectName(_fromUtf8("menuSettings")) self.menuHelp = QMenu(self.menubar) self.menuHelp.setObjectName(_fromUtf8("menuHelp")) MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName(_fromUtf8("statusbar")) MainWindow.setStatusBar(self.statusbar) self.actionExit = QAction(MainWindow) self.actionExit.setObjectName(_fromUtf8("actionExit")) self.actionOpen = QAction(MainWindow) self.actionOpen.setObjectName(_fromUtf8("actionOpen")) self.actionSave = QAction(MainWindow) self.actionSave.setObjectName(_fromUtf8("actionSave")) self.actionImportNmap = QAction(MainWindow) self.actionImportNmap.setObjectName(_fromUtf8("actionImportNmap")) self.actionSaveAs = QAction(MainWindow) self.actionSaveAs.setObjectName(_fromUtf8("actionSaveAs")) self.actionNew = QAction(MainWindow) self.actionNew.setObjectName(_fromUtf8("actionNew")) self.actionAddHosts = QAction(MainWindow) self.actionAddHosts.setObjectName(_fromUtf8("actionAddHosts")) self.menuFile.addAction(self.actionNew) self.menuFile.addAction(self.actionOpen) self.menuFile.addAction(self.actionSave) self.menuFile.addAction(self.actionSaveAs) self.menuFile.addSeparator() self.menuFile.addAction(self.actionAddHosts) self.menuFile.addAction(self.actionImportNmap) self.menuFile.addSeparator() self.menuFile.addAction(self.actionExit) self.menubar.addAction(self.menuFile.menuAction()) # self.menubar.addAction(self.menuEdit.menuAction()) # self.menubar.addAction(self.menuSettings.menuAction()) # self.menubar.addAction(self.menuSettings.menuAction()) # self.actionSettings = QAction(MainWindow) # self.actionSettings.setObjectName(_fromUtf8("getSettingsMenu")) # self.menuSettings.addAction(self.actionSettings) self.actionHelp = QAction(MainWindow) self.actionHelp.setObjectName(_fromUtf8("getHelp")) self.menuHelp.addAction(self.actionHelp) self.menubar.addAction(self.menuHelp.menuAction()) def setDefaultIndexes(self): self.MainTabWidget.setCurrentIndex(1) self.HostsTabWidget.setCurrentIndex(1) self.ServicesTabWidget.setCurrentIndex(1) self.BruteTabWidget.setCurrentIndex(1) self.BottomTabWidget.setCurrentIndex(0) def retranslateUi(self, MainWindow): MainWindow.setWindowTitle( QApplication.translate("MainWindow", "SPARTA 2.0", None)) self.HostsTabWidget.setTabText( self.HostsTabWidget.indexOf(self.HostsTab), QApplication.translate("MainWindow", "Hosts", None)) self.HostsTabWidget.setTabText( self.HostsTabWidget.indexOf(self.ServicesLeftTab), QApplication.translate("MainWindow", "Services", None)) self.HostsTabWidget.setTabText( self.HostsTabWidget.indexOf(self.ToolsTab), QApplication.translate("MainWindow", "Tools", None)) self.ServicesTabWidget.setTabText( self.ServicesTabWidget.indexOf(self.ServicesRightTab), QApplication.translate("MainWindow", "Services", None)) self.ServicesTabWidget.setTabText( self.ServicesTabWidget.indexOf(self.ScriptsTab), QApplication.translate("MainWindow", "Scripts", None)) self.ServicesTabWidget.setTabText( self.ServicesTabWidget.indexOf(self.InformationTab), QApplication.translate("MainWindow", "Information", None)) self.ServicesTabWidget.setTabText( self.ServicesTabWidget.indexOf(self.NotesTab), QApplication.translate("MainWindow", "Notes", None)) # self.ServicesTabWidget.setTabText(self.ServicesTabWidget.indexOf(self.ScreenshotsTab), QApplication.translate("MainWindow", "Screenshots", None)) self.MainTabWidget.setTabText( self.MainTabWidget.indexOf(self.ScanTab), QApplication.translate("MainWindow", "Scan", None)) #self.BruteTabWidget.setTabText(self.BruteTabWidget.indexOf(self.tab), QApplication.translate("MainWindow", "Tab 1", None)) #self.BruteTabWidget.setTabText(self.BruteTabWidget.indexOf(self.tab_2), QApplication.translate("MainWindow", "Tab 2", None)) self.MainTabWidget.setTabText( self.MainTabWidget.indexOf(self.BruteTab), QApplication.translate("MainWindow", "Brute", None)) self.BottomTabWidget.setTabText( self.BottomTabWidget.indexOf(self.LogTab), QApplication.translate("MainWindow", "Log", None)) # self.BottomTabWidget.setTabText(self.BottomTabWidget.indexOf(self.TerminalTab), QApplication.translate("MainWindow", "Terminal", None)) # self.BottomTabWidget.setTabText(self.BottomTabWidget.indexOf(self.PythonTab), QApplication.translate("MainWindow", "Python", None)) self.menuFile.setTitle( QApplication.translate("MainWindow", "File", None)) # self.menuEdit.setTitle(QApplication.translate("MainWindow", "Edit", None)) # self.menuSettings.setTitle(QApplication.translate("MainWindow", "Settings", None)) self.menuHelp.setTitle( QApplication.translate("MainWindow", "Help", None)) self.actionExit.setText( QApplication.translate("MainWindow", "Exit", None)) self.actionExit.setToolTip( QApplication.translate("MainWindow", "Exit the application", None)) self.actionExit.setShortcut( QApplication.translate("MainWindow", "Ctrl+Q", None)) self.actionOpen.setText( QApplication.translate("MainWindow", "Open", None)) self.actionOpen.setToolTip( QApplication.translate("MainWindow", "Open an existing project file", None)) self.actionOpen.setShortcut( QApplication.translate("MainWindow", "Ctrl+O", None)) self.actionSave.setText( QApplication.translate("MainWindow", "Save", None)) self.actionSave.setToolTip( QApplication.translate("MainWindow", "Save the current project", None)) self.actionSave.setShortcut( QApplication.translate("MainWindow", "Ctrl+S", None)) self.actionImportNmap.setText( QApplication.translate("MainWindow", "Import nmap", None)) self.actionImportNmap.setToolTip( QApplication.translate("MainWindow", "Import an nmap xml file", None)) self.actionImportNmap.setShortcut( QApplication.translate("MainWindow", "Ctrl+I", None)) self.actionSaveAs.setText( QApplication.translate("MainWindow", "Save As", None)) self.actionNew.setText( QApplication.translate("MainWindow", "New", None)) self.actionNew.setShortcut( QApplication.translate("MainWindow", "Ctrl+N", None)) self.actionAddHosts.setText( QApplication.translate("MainWindow", "Add host(s) to scope", None)) self.actionAddHosts.setShortcut( QApplication.translate("MainWindow", "Ctrl+H", None)) #self.actionSettings.setText(QApplication.translate("MainWindow", "Preferences", None)) self.actionHelp.setText( QApplication.translate("MainWindow", "Help", None)) self.actionHelp.setShortcut( QApplication.translate("MainWindow", "F1", None))
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Untitled") icon = os.path.join(BASE_DIR, 'ide/Icon.ico') self.setWindowIcon(QIcon(icon)) self.saveLoad = SaveLoad() self.fileName = None self.setupUI() def setupUI(self): centralWidget = QWidget(self) layout = QHBoxLayout(centralWidget) self.fileSysView = QTreeView(centralWidget) self.setupFileSystemViewer() self.editor = QsciScintilla(centralWidget) self.setupEditor() layout.addWidget(self.fileSysView, 1) layout.addWidget(self.editor, 3) self.setCentralWidget(centralWidget) self.setMinimumSize(700, 500) self.defaultMenuBar = QMenuBar(self) self.setupMenus() self.setMenuBar(self.defaultMenuBar) self.show() def setupEditor(self): self.editor.setFont(QFont("Times New Roman", 12)) self.editor.setMargins(2) self.editor.setMarginType(0, QsciScintilla.NumberMargin) self.editor.setMarginType(1, QsciScintilla.SymbolMargin) self.editor.setMarginWidth(0, "000") self.editor.setMarginWidth(1, "00") self.editor.markerDefine(QsciScintilla.RightTriangle, 1) if system() == "Windows": self.editor.setEolMode(QsciScintilla.EolWindows) elif system() == "Linux": self.editor.setEolMode(QsciScintilla.EolUnix) elif system() == "Mac": self.editor.setEolMode(QsciScintilla.EolMac) else: print("Using Windows EOL") self.editor.setEolMode(QsciScintilla.EolWindows) self.editor.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.editor.setIndentationsUseTabs(True) self.editor.setTabWidth(4) self.editor.setIndentationGuides(True) self.editor.setTabIndents(True) self.editor.setAutoIndent(True) self.editor.setCaretForegroundColor(QColor("#ff11214b")) self.editor.setCaretLineVisible(True) self.editor.setCaretLineBackgroundColor(QColor("#1f0000ff")) self.editor.setUtf8(True) self.editor.setMarginSensitivity(1, True) self.editor.marginClicked.connect(self.margin_clicked) self.editor.marginRightClicked.connect(self.margin_right_clicked) self.lexer = QsciLexerPython() self.lexer.setFont(QFont("Times New Roman", 12)) self.editor.setLexer(self.lexer) self.editor.textChanged.connect(self.fileChanged) def setupFileSystemViewer(self): model = QFileSystemModel() model.setRootPath("/") self.fileSysView.setModel(model) self.fileSysView.hideColumn(1) self.fileSysView.hideColumn(2) self.fileSysView.hideColumn(3) self.fileSysView.doubleClicked.connect(self.openFile) def setupMenus(self): fileMenu = QMenu(self.defaultMenuBar) fileMenu.setTitle("File") editMenu = QMenu(self.defaultMenuBar) editMenu.setTitle("Edit") viewMenu = QMenu(self.defaultMenuBar) viewMenu.setTitle("View") runMenu = QMenu(self.defaultMenuBar) runMenu.setTitle("Run") settingsMenu = QMenu(self.defaultMenuBar) settingsMenu.setTitle("Settings") self.actionNew = QAction(self) self.actionNew.setText("New") self.actionNew.setShortcut("Ctrl+N") self.actionOpen = QAction(self) self.actionOpen.setText("Open") self.actionOpen.setShortcut("Ctrl+O") self.actionSave = QAction(self) self.actionSave.setText("Save") self.actionSave.setShortcut("Ctrl+S") self.actionSaveAs = QAction(self) self.actionSaveAs.setText("Save As") self.actionSaveAs.setShortcut("Ctrl+Shift+S") self.actionExit = QAction(self) self.actionExit.setText("Exit") self.actionExit.setShortcut("Alt+X") self.actionUndo = QAction(self) self.actionUndo.setText("Undo") self.actionUndo.setShortcut("Ctrl+Z") self.actionRedo = QAction(self) self.actionRedo.setText("Redo") self.actionRedo.setShortcut("Ctrl+Shift+Z") self.actionSelectAll = QAction(self) self.actionSelectAll.setText("Select all") self.actionSelectAll.setShortcut("Ctrl+A") self.actionCut = QAction(self) self.actionCut.setText("Cut") self.actionCut.setShortcut("Ctrl+X") self.actionCopy = QAction(self) self.actionCopy.setText("Copy") self.actionCopy.setShortcut("Ctrl+C") self.actionPaste = QAction(self) self.actionPaste.setText("Paste") self.actionPaste.setShortcut("Ctrl+V") self.actionFind = QAction(self) self.actionFind.setText("Find") self.actionFind.setShortcut("Ctrl+F") self.actionReplace = QAction(self) self.actionReplace.setText("Replace") self.actionReplace.setShortcut("Ctrl+H") self.actionRun = QAction(self) self.actionRun.setText("Run") self.actionRun.setShortcut("F5") self.actionRunCustom = QAction(self) self.actionRunCustom.setText("Run Customized") self.actionRunCustom.setShortcut("Shift+F5") self.actionShell = QAction(self) self.actionShell.setText("Python shell") self.actionShell.setShortcut("Alt+S") self.actionFont = QAction(self) self.actionFont.setText("Font") self.actionEncoding = QAction(self) self.actionEncoding.setText("Encoding") fileMenu.addAction(self.actionNew) fileMenu.addAction(self.actionOpen) fileMenu.addAction(self.actionSave) fileMenu.addAction(self.actionSaveAs) fileMenu.addSeparator() fileMenu.addAction(self.actionExit) editMenu.addAction(self.actionUndo) editMenu.addAction(self.actionRedo) editMenu.addSeparator() editMenu.addAction(self.actionSelectAll) editMenu.addSeparator() editMenu.addAction(self.actionCut) editMenu.addAction(self.actionCopy) editMenu.addAction(self.actionPaste) viewMenu.addAction(self.actionFind) viewMenu.addAction(self.actionReplace) runMenu.addAction(self.actionRun) runMenu.addAction(self.actionRunCustom) runMenu.addAction(self.actionShell) settingsMenu.addAction(self.actionFont) settingsMenu.addAction(self.actionEncoding) self.defaultMenuBar.addAction(fileMenu.menuAction()) self.defaultMenuBar.addAction(editMenu.menuAction()) self.defaultMenuBar.addAction(viewMenu.menuAction()) self.defaultMenuBar.addAction(runMenu.menuAction()) self.defaultMenuBar.addAction(settingsMenu.menuAction()) self.actionNew.triggered.connect(self.new) self.actionOpen.triggered.connect(self.open) self.actionSave.triggered.connect(self.save) self.actionSaveAs.triggered.connect(self.saveAs) self.actionExit.triggered.connect(self.close) self.actionUndo.triggered.connect(self.editor.undo) self.actionRedo.triggered.connect(self.editor.redo) self.actionSelectAll.triggered.connect( lambda: self.editor.selectAll(True)) self.actionCut.triggered.connect(self.editor.cut) self.actionCopy.triggered.connect(self.editor.copy) self.actionPaste.triggered.connect(self.editor.paste) self.actionFind.triggered.connect(self.find) self.actionReplace.triggered.connect(self.replace) self.actionRun.triggered.connect(self.run) self.actionRunCustom.triggered.connect(self.runCustom) self.actionShell.triggered.connect(self.shell) self.actionFont.triggered.connect(self.Font) def margin_clicked(self, margin_nr, line_nr, state): self.editor.markerAdd(line_nr, margin_nr) def margin_right_clicked(self, margin_nr, line_nr, state): self.editor.markerDelete(line_nr, margin_nr) def new(self): if self.windowTitle().endswith("*"): if (Dialogs().Question( self, "Do you want to save your file?") == "accept"): if self.filename is None: self.saveAs() else: self.save() self.editor.setText("") self.setWindowTitle("Untitled") def open(self): if self.windowTitle().endswith("*"): if (Dialogs().Question( self, "Do you want to save your file?") == "accept"): if self.filename is None: self.saveAs() else: self.save() filename = self.saveLoad.OpenDialog() data = Open(filename) if data is not None: self.editor.setText(data) self.setWindowTitle(filename) self.filename = filename def save(self): if self.filename is None: self.saveAs() else: returnval = Save(self.editor.text(), self.filename) if (returnval): Dialogs().Message(self, "File saved successfully") self.setWindowTitle(self.filename) else: Dialogs().Error(self, "File could not be saved") def saveAs(self): self.filename = self.saveLoad.SaveDialog() returnval = Save(self.editor.text(), self.filename) if (returnval): Dialogs().Message(self, "File saved successfully") self.setWindowTitle(self.filename) else: Dialogs().Error(self, "File could not be saved") def run(self): if self.filename is None: self.saveAs() Runfile(self.filename) def runCustom(self): if self.filename is None: self.saveAs() if self.filename != "": print(len(self.filename)) option, ok = QInputDialog().getText( self, "Customized run", "Enter parameters for sys.argv", QLineEdit.Normal, " ") if ok: Runfile(self.filename, option) def shell(self): Shell() def Font(self): font, ok = QFontDialog.getFont() if ok: self.editor.setFont(font) self.lexer.setFont(font) self.editor.setLexer(self.lexer) def openFile(self, signal): fileName = self.fileSysView.model().filePath(signal) if fileName.endswith("py") or fileName.endswith("pyw"): if self.windowTitle().endswith("*"): if Dialogs().Question( self, "Do you want to save your file?") == "accept": if self.filename is None: self.saveAs() else: self.save() data = Open(fileName) if data is not None: self.editor.setText(data) self.setWindowTitle(fileName) self.filename = fileName def fileChanged(self): title = self.windowTitle() if not (title.endswith("*")): self.setWindowTitle(title + " *") def replace(self): replaceObj = replaceDialog(self, self.editor) def find(self): findObj = findDialog(self, self.editor)
class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.resize(1000, 800) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout.setSpacing(5) self.gridLayout.setObjectName(u"gridLayout") self.gridLayout.setContentsMargins(10, 10, 10, 10) self.lineEdit = QLineEdit(self.centralwidget) self.lineEdit.setObjectName(u"lineEdit") regex = QtCore.QRegExp("^[0-9A-Za-z]{4}( [0-9A-Za-z]{4})*") validator = QtGui.QRegExpValidator(regex) self.lineEdit.setValidator(validator) self.gridLayout.addWidget(self.lineEdit, 0, 0, 1, 1) self.getMETAR = QPushButton(self.centralwidget) self.getMETAR.setObjectName(u"getMETAR") self.gridLayout.addWidget(self.getMETAR, 0, 1, 1, 1) self.clearButton = QPushButton(self.centralwidget) self.clearButton.setObjectName(u"clearButton") self.gridLayout.addWidget(self.clearButton, 0, 2, 1, 1) # Maintab self.tabWidget = QTabWidget(self.centralwidget) self.tabWidget.setObjectName(u"tabWidget") #Tab METAR self.tab_1 = QWidget() self.tab_1.setObjectName(u"tab_1") self.gridLayout_2 = QGridLayout(self.tab_1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.tableWidget = QTableWidget(self.tab_1) self.tableWidget.setObjectName(u"tableWidget") self.tableWidget.setColumnCount(3) self.tableWidget.setRowCount(0) self.tableWidget.horizontalHeader().setCascadingSectionResizes(True) self.tableWidget.horizontalHeader().setVisible(True) self.tableWidget.verticalHeader().setVisible(False) self.tableWidget.setHorizontalHeaderLabels( [u"ICAO", u"TIME", u"METAR CODE"]) self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.gridLayout_2.addWidget(self.tableWidget, 0, 0, 1, 1) self.tabWidget.addTab(self.tab_1, "") self.textBrowser = QtWidgets.QTextBrowser(self.tab_1) self.textBrowser.setObjectName("textBrowser") self.gridLayout_2.addWidget(self.textBrowser, 1, 0, 1, 1) self.tabWidget.addTab(self.tab_1, "") #Tab_METAR_END #Tab_TAF self.tab_2 = QWidget() self.tab_2.setObjectName(u"tab_2") self.gridLayout_3 = QGridLayout(self.tab_2) self.gridLayout_3.setObjectName(u"gridLayout_3") self.textBrowser_3 = QtWidgets.QTextBrowser(self.tab_2) self.textBrowser_3.setObjectName("textBrowser_3") self.gridLayout_3.addWidget(self.textBrowser_3, 1, 0, 1, 1) self.tabWidget.addTab(self.tab_2, "") #Tab_TAF_END self.tab_3 = QWidget() self.tab_3.setObjectName(u"tab_3") self.gridLayout_4 = QGridLayout(self.tab_3) self.gridLayout_4.setObjectName(u"gridLayout_4") self.tableWidget_3 = QTableWidget(self.tab_3) self.tableWidget_3.setObjectName(u"tableWidget_3") self.gridLayout_4.addWidget(self.tableWidget_3, 0, 0, 1, 1) self.tabWidget.addTab(self.tab_3, "") self.gridLayout.addWidget(self.tabWidget, 2, 0, 1, 1) #Maintab_END self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.checkBox = QtWidgets.QCheckBox(self.centralwidget) self.checkBox.setEnabled(True) self.checkBox.setStatusTip("") self.checkBox.setChecked(True) self.checkBox.setTristate(False) self.checkBox.setObjectName("checkBox") self.verticalLayout.addWidget(self.checkBox) self.checkBox_2 = QtWidgets.QCheckBox(self.centralwidget) self.checkBox_2.setObjectName("checkBox_2") self.verticalLayout.addWidget(self.checkBox_2) self.checkBox_3 = QtWidgets.QCheckBox(self.centralwidget) self.checkBox_3.setObjectName("checkBox_3") self.verticalLayout.addWidget(self.checkBox_3) self.gridLayout.addLayout(self.verticalLayout, 2, 1, 1, 2) #WIP self.checkBox.setChecked(True) self.checkBox.setDisabled(True) self.checkBox_2.setChecked(True) self.checkBox_2.setDisabled(True) self.checkBox_3.setDisabled(True) #END_WIP MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 294, 29)) self.menubar.setObjectName("menubar") self.menuFile = QMenu(self.menubar) self.menuFile.setObjectName("menuFile") MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionQuit = QAction(MainWindow) self.actionQuit.setObjectName("actionQuit") self.menuFile.addAction(self.actionQuit) self.menubar.addAction(self.menuFile.menuAction()) self.retranslateUi(MainWindow) self.actionQuit.triggered.connect(MainWindow.close) self.tabWidget.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "METAR")) self.menuFile.setTitle(_translate("MainWindow", "Fi&le")) self.actionQuit.setText(_translate("MainWindow", "&Quit")) self.getMETAR.setText( QCoreApplication.translate("MainWindow", u"GET", None)) self.clearButton.setText( QCoreApplication.translate("MainWindow", u"CLEAR", None)) self.tabWidget.setTabText( self.tabWidget.indexOf(self.tab_1), QCoreApplication.translate("MainWindow", u"METAR", None)) self.tabWidget.setTabText( self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("MainWindow", u"TAF", None)) self.tabWidget.setTabText( self.tabWidget.indexOf(self.tab_3), QCoreApplication.translate("MainWindow", u"NOTAM", None)) self.checkBox_2.setText( QCoreApplication.translate("MainWindow", u"TAF", None)) self.checkBox_3.setText( QCoreApplication.translate("MainWindow", u"NOTAM", None)) self.checkBox.setText( QCoreApplication.translate("MainWindow", u"METAR", None))
class ResultWindow(QMainWindow): def __init__(self, parent, app, **kwargs): super().__init__(parent, **kwargs) self.app = app self._setupUi() if app.model.app_mode == AppMode.Picture: MODEL_CLASS = ResultsModelPicture elif app.model.app_mode == AppMode.Music: MODEL_CLASS = ResultsModelMusic else: MODEL_CLASS = ResultsModelStandard self.resultsModel = MODEL_CLASS(self.app, self.resultsView) self.stats = StatsLabel(app.model.stats_label, self.statusLabel) self._update_column_actions_status() self.menuColumns.triggered.connect(self.columnToggled) self.resultsView.doubleClicked.connect(self.resultsDoubleClicked) self.resultsView.spacePressed.connect(self.resultsSpacePressed) self.detailsButton.clicked.connect(self.actionDetails.triggered) self.dupesOnlyCheckBox.stateChanged.connect(self.powerMarkerTriggered) self.deltaValuesCheckBox.stateChanged.connect(self.deltaTriggered) self.searchEdit.searchChanged.connect(self.searchChanged) self.app.willSavePrefs.connect(self.appWillSavePrefs) def _setupActions(self): # (name, shortcut, icon, desc, func) ACTIONS = [ ("actionDetails", "Ctrl+I", "", tr("Details"), self.detailsTriggered), ("actionActions", "", "", tr("Actions"), self.actionsTriggered), ( "actionPowerMarker", "Ctrl+1", "", tr("Show Dupes Only"), self.powerMarkerTriggered, ), ("actionDelta", "Ctrl+2", "", tr("Show Delta Values"), self.deltaTriggered), ( "actionDeleteMarked", "Ctrl+D", "", tr("Send Marked to Recycle Bin..."), self.deleteTriggered, ), ( "actionMoveMarked", "Ctrl+M", "", tr("Move Marked to..."), self.moveTriggered, ), ( "actionCopyMarked", "Ctrl+Shift+M", "", tr("Copy Marked to..."), self.copyTriggered, ), ( "actionRemoveMarked", "Ctrl+R", "", tr("Remove Marked from Results"), self.removeMarkedTriggered, ), ( "actionReprioritize", "", "", tr("Re-Prioritize Results..."), self.reprioritizeTriggered, ), ( "actionRemoveSelected", "Ctrl+Del", "", tr("Remove Selected from Results"), self.removeSelectedTriggered, ), ( "actionIgnoreSelected", "Ctrl+Shift+Del", "", tr("Add Selected to Ignore List"), self.addToIgnoreListTriggered, ), ( "actionMakeSelectedReference", "Ctrl+Space", "", tr("Make Selected into Reference"), self.app.model.make_selected_reference, ), ( "actionOpenSelected", "Ctrl+O", "", tr("Open Selected with Default Application"), self.openTriggered, ), ( "actionRevealSelected", "Ctrl+Shift+O", "", tr("Open Containing Folder of Selected"), self.revealTriggered, ), ( "actionRenameSelected", "F2", "", tr("Rename Selected"), self.renameTriggered, ), ("actionMarkAll", "Ctrl+A", "", tr("Mark All"), self.markAllTriggered), ( "actionMarkNone", "Ctrl+Shift+A", "", tr("Mark None"), self.markNoneTriggered, ), ( "actionInvertMarking", "Ctrl+Alt+A", "", tr("Invert Marking"), self.markInvertTriggered, ), ( "actionMarkSelected", "", "", tr("Mark Selected"), self.markSelectedTriggered, ), ( "actionExportToHTML", "", "", tr("Export To HTML"), self.app.model.export_to_xhtml, ), ( "actionExportToCSV", "", "", tr("Export To CSV"), self.app.model.export_to_csv, ), ( "actionSaveResults", "Ctrl+S", "", tr("Save Results..."), self.saveResultsTriggered, ), ( "actionInvokeCustomCommand", "Ctrl+Alt+I", "", tr("Invoke Custom Command"), self.app.invokeCustomCommand, ), ] createActions(ACTIONS, self) self.actionDelta.setCheckable(True) self.actionPowerMarker.setCheckable(True) def _setupMenu(self): self.menubar = QMenuBar() self.menubar.setGeometry(QRect(0, 0, 630, 22)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle(tr("File")) self.menuMark = QMenu(self.menubar) self.menuMark.setTitle(tr("Mark")) self.menuActions = QMenu(self.menubar) self.menuActions.setTitle(tr("Actions")) self.menuColumns = QMenu(self.menubar) self.menuColumns.setTitle(tr("Columns")) self.menuView = QMenu(self.menubar) self.menuView.setTitle(tr("View")) self.menuHelp = QMenu(self.menubar) self.menuHelp.setTitle(tr("Help")) self.setMenuBar(self.menubar) self.menuActions.addAction(self.actionDeleteMarked) self.menuActions.addAction(self.actionMoveMarked) self.menuActions.addAction(self.actionCopyMarked) self.menuActions.addAction(self.actionRemoveMarked) self.menuActions.addAction(self.actionReprioritize) self.menuActions.addSeparator() self.menuActions.addAction(self.actionRemoveSelected) self.menuActions.addAction(self.actionIgnoreSelected) self.menuActions.addAction(self.actionMakeSelectedReference) self.menuActions.addSeparator() self.menuActions.addAction(self.actionOpenSelected) self.menuActions.addAction(self.actionRevealSelected) self.menuActions.addAction(self.actionInvokeCustomCommand) self.menuActions.addAction(self.actionRenameSelected) self.menuMark.addAction(self.actionMarkAll) self.menuMark.addAction(self.actionMarkNone) self.menuMark.addAction(self.actionInvertMarking) self.menuMark.addAction(self.actionMarkSelected) self.menuView.addAction(self.actionPowerMarker) self.menuView.addAction(self.actionDelta) self.menuView.addSeparator() self.menuView.addAction(self.actionDetails) self.menuView.addAction(self.app.actionIgnoreList) self.menuView.addAction(self.app.actionPreferences) self.menuHelp.addAction(self.app.actionShowHelp) self.menuHelp.addAction(self.app.actionOpenDebugLog) self.menuHelp.addAction(self.app.actionAbout) self.menuFile.addAction(self.actionSaveResults) self.menuFile.addAction(self.actionExportToHTML) self.menuFile.addAction(self.actionExportToCSV) self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionQuit) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuMark.menuAction()) self.menubar.addAction(self.menuActions.menuAction()) self.menubar.addAction(self.menuColumns.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) # Columns menu menu = self.menuColumns self._column_actions = [] for index, (display, visible) in enumerate( self.app.model.result_table.columns.menu_items() ): action = menu.addAction(display) action.setCheckable(True) action.setChecked(visible) action.item_index = index self._column_actions.append(action) menu.addSeparator() action = menu.addAction(tr("Reset to Defaults")) action.item_index = -1 # Action menu actionMenu = QMenu(tr("Actions"), self.menubar) actionMenu.addAction(self.actionDeleteMarked) actionMenu.addAction(self.actionMoveMarked) actionMenu.addAction(self.actionCopyMarked) actionMenu.addAction(self.actionRemoveMarked) actionMenu.addSeparator() actionMenu.addAction(self.actionRemoveSelected) actionMenu.addAction(self.actionIgnoreSelected) actionMenu.addAction(self.actionMakeSelectedReference) actionMenu.addSeparator() actionMenu.addAction(self.actionOpenSelected) actionMenu.addAction(self.actionRevealSelected) actionMenu.addAction(self.actionInvokeCustomCommand) actionMenu.addAction(self.actionRenameSelected) self.actionActions.setMenu(actionMenu) self.actionsButton.setMenu(self.actionActions.menu()) def _setupUi(self): self.setWindowTitle(tr("{} Results").format(self.app.NAME)) self.resize(630, 514) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.actionsButton = QPushButton(tr("Actions")) self.detailsButton = QPushButton(tr("Details")) self.dupesOnlyCheckBox = QCheckBox(tr("Dupes Only")) self.deltaValuesCheckBox = QCheckBox(tr("Delta Values")) self.searchEdit = SearchEdit() self.searchEdit.setMaximumWidth(300) self.horizontalLayout = horizontalWrap( [ self.actionsButton, self.detailsButton, self.dupesOnlyCheckBox, self.deltaValuesCheckBox, None, self.searchEdit, 8, ] ) self.horizontalLayout.setSpacing(8) self.verticalLayout.addLayout(self.horizontalLayout) self.resultsView = ResultsView(self.centralwidget) self.resultsView.setSelectionMode(QAbstractItemView.ExtendedSelection) self.resultsView.setSelectionBehavior(QAbstractItemView.SelectRows) self.resultsView.setSortingEnabled(True) self.resultsView.setWordWrap(False) self.resultsView.verticalHeader().setVisible(False) h = self.resultsView.horizontalHeader() h.setHighlightSections(False) h.setSectionsMovable(True) h.setStretchLastSection(False) h.setDefaultAlignment(Qt.AlignLeft) self.verticalLayout.addWidget(self.resultsView) self.setCentralWidget(self.centralwidget) self._setupActions() self._setupMenu() self.statusbar = QStatusBar(self) self.statusbar.setSizeGripEnabled(True) self.setStatusBar(self.statusbar) self.statusLabel = QLabel(self) self.statusbar.addPermanentWidget(self.statusLabel, 1) if self.app.prefs.resultWindowIsMaximized: self.setWindowState(self.windowState() | Qt.WindowMaximized) else: if self.app.prefs.resultWindowRect is not None: self.setGeometry(self.app.prefs.resultWindowRect) # if not on any screen move to center of default screen # moves to center of closest screen if partially off screen frame = self.frameGeometry() if QDesktopWidget().screenNumber(self) == -1: moveToScreenCenter(self) elif QDesktopWidget().availableGeometry(self).contains(frame) is False: frame.moveCenter(QDesktopWidget().availableGeometry(self).center()) self.move(frame.topLeft()) else: moveToScreenCenter(self) # --- Private def _update_column_actions_status(self): # Update menu checked state menu_items = self.app.model.result_table.columns.menu_items() for action, (display, visible) in zip(self._column_actions, menu_items): action.setChecked(visible) # --- Actions def actionsTriggered(self): self.actionsButton.showMenu() def addToIgnoreListTriggered(self): self.app.model.add_selected_to_ignore_list() def copyTriggered(self): self.app.model.copy_or_move_marked(True) def deleteTriggered(self): self.app.model.delete_marked() def deltaTriggered(self, state=None): # The sender can be either the action or the checkbox, but both have a isChecked() method. self.resultsModel.delta_values = self.sender().isChecked() self.actionDelta.setChecked(self.resultsModel.delta_values) self.deltaValuesCheckBox.setChecked(self.resultsModel.delta_values) def detailsTriggered(self): self.app.show_details() def markAllTriggered(self): self.app.model.mark_all() def markInvertTriggered(self): self.app.model.mark_invert() def markNoneTriggered(self): self.app.model.mark_none() def markSelectedTriggered(self): self.app.model.toggle_selected_mark_state() def moveTriggered(self): self.app.model.copy_or_move_marked(False) def openTriggered(self): self.app.model.open_selected() def powerMarkerTriggered(self, state=None): # see deltaTriggered self.resultsModel.power_marker = self.sender().isChecked() self.actionPowerMarker.setChecked(self.resultsModel.power_marker) self.dupesOnlyCheckBox.setChecked(self.resultsModel.power_marker) def preferencesTriggered(self): self.app.show_preferences() def removeMarkedTriggered(self): self.app.model.remove_marked() def removeSelectedTriggered(self): self.app.model.remove_selected() def renameTriggered(self): index = self.resultsView.selectionModel().currentIndex() # Our index is the current row, with column set to 0. Our filename column is 1 and that's # what we want. index = index.sibling(index.row(), 1) self.resultsView.edit(index) def reprioritizeTriggered(self): dlg = PrioritizeDialog(self, self.app) result = dlg.exec() if result == QDialog.Accepted: dlg.model.perform_reprioritization() def revealTriggered(self): self.app.model.reveal_selected() def saveResultsTriggered(self): title = tr("Select a file to save your results to") files = tr("dupeGuru Results (*.dupeguru)") destination, chosen_filter = QFileDialog.getSaveFileName(self, title, "", files) if destination: if not destination.endswith(".dupeguru"): destination = "{}.dupeguru".format(destination) self.app.model.save_as(destination) self.app.recentResults.insertItem(destination) # --- Events def appWillSavePrefs(self): prefs = self.app.prefs prefs.resultWindowIsMaximized = self.isMaximized() prefs.resultWindowRect = self.geometry() def columnToggled(self, action): index = action.item_index if index == -1: self.app.model.result_table.columns.reset_to_defaults() self._update_column_actions_status() else: visible = self.app.model.result_table.columns.toggle_menu_item(index) action.setChecked(visible) def contextMenuEvent(self, event): self.actionActions.menu().exec_(event.globalPos()) def resultsDoubleClicked(self, modelIndex): self.app.model.open_selected() def resultsSpacePressed(self): self.app.model.toggle_selected_mark_state() def searchChanged(self): self.app.model.apply_filter(self.searchEdit.text()) def closeEvent(self, event): # this saves the location of the results window when it is closed self.appWillSavePrefs()
class ResultWindow(QMainWindow): def __init__(self, parent, app, **kwargs): super().__init__(parent, **kwargs) self.app = app self._setupUi() self.resultsModel = app.RESULT_MODEL_CLASS(self.app, self.resultsView) self.stats = StatsLabel(app.model.stats_label, self.statusLabel) self._update_column_actions_status() self.menuColumns.triggered.connect(self.columnToggled) self.resultsView.doubleClicked.connect(self.resultsDoubleClicked) self.resultsView.spacePressed.connect(self.resultsSpacePressed) self.detailsButton.clicked.connect(self.actionDetails.triggered) self.dupesOnlyCheckBox.stateChanged.connect(self.powerMarkerTriggered) self.deltaValuesCheckBox.stateChanged.connect(self.deltaTriggered) self.searchEdit.searchChanged.connect(self.searchChanged) self.app.willSavePrefs.connect(self.appWillSavePrefs) def _setupActions(self): # (name, shortcut, icon, desc, func) ACTIONS = [ ('actionDetails', 'Ctrl+I', '', tr("Details"), self.detailsTriggered), ('actionActions', '', '', tr("Actions"), self.actionsTriggered), ('actionPowerMarker', 'Ctrl+1', '', tr("Show Dupes Only"), self.powerMarkerTriggered), ('actionDelta', 'Ctrl+2', '', tr("Show Delta Values"), self.deltaTriggered), ('actionDeleteMarked', 'Ctrl+D', '', tr("Send Marked to Recycle Bin..."), self.deleteTriggered), ('actionMoveMarked', 'Ctrl+M', '', tr("Move Marked to..."), self.moveTriggered), ('actionCopyMarked', 'Ctrl+Shift+M', '', tr("Copy Marked to..."), self.copyTriggered), ('actionRemoveMarked', 'Ctrl+R', '', tr("Remove Marked from Results"), self.removeMarkedTriggered), ('actionReprioritize', '', '', tr("Re-Prioritize Results..."), self.reprioritizeTriggered), ('actionRemoveSelected', 'Ctrl+Del', '', tr("Remove Selected from Results"), self.removeSelectedTriggered), ('actionIgnoreSelected', 'Ctrl+Shift+Del', '', tr("Add Selected to Ignore List"), self.addToIgnoreListTriggered), ('actionMakeSelectedReference', 'Ctrl+Space', '', tr("Make Selected into Reference"), self.app.model.make_selected_reference), ('actionOpenSelected', 'Ctrl+O', '', tr("Open Selected with Default Application"), self.openTriggered), ('actionRevealSelected', 'Ctrl+Shift+O', '', tr("Open Containing Folder of Selected"), self.revealTriggered), ('actionRenameSelected', 'F2', '', tr("Rename Selected"), self.renameTriggered), ('actionMarkAll', 'Ctrl+A', '', tr("Mark All"), self.markAllTriggered), ('actionMarkNone', 'Ctrl+Shift+A', '', tr("Mark None"), self.markNoneTriggered), ('actionInvertMarking', 'Ctrl+Alt+A', '', tr("Invert Marking"), self.markInvertTriggered), ('actionMarkSelected', '', '', tr("Mark Selected"), self.markSelectedTriggered), ('actionExportToHTML', '', '', tr("Export To HTML"), self.app.model.export_to_xhtml), ('actionExportToCSV', '', '', tr("Export To CSV"), self.app.model.export_to_csv), ('actionSaveResults', 'Ctrl+S', '', tr("Save Results..."), self.saveResultsTriggered), ('actionInvokeCustomCommand', 'Ctrl+Alt+I', '', tr("Invoke Custom Command"), self.app.invokeCustomCommand), ] createActions(ACTIONS, self) self.actionDelta.setCheckable(True) self.actionPowerMarker.setCheckable(True) def _setupMenu(self): self.menubar = QMenuBar() self.menubar.setGeometry(QRect(0, 0, 630, 22)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle(tr("File")) self.menuMark = QMenu(self.menubar) self.menuMark.setTitle(tr("Mark")) self.menuActions = QMenu(self.menubar) self.menuActions.setTitle(tr("Actions")) self.menuColumns = QMenu(self.menubar) self.menuColumns.setTitle(tr("Columns")) self.menuView = QMenu(self.menubar) self.menuView.setTitle(tr("View")) self.menuHelp = QMenu(self.menubar) self.menuHelp.setTitle(tr("Help")) self.setMenuBar(self.menubar) self.menuActions.addAction(self.actionDeleteMarked) self.menuActions.addAction(self.actionMoveMarked) self.menuActions.addAction(self.actionCopyMarked) self.menuActions.addAction(self.actionRemoveMarked) self.menuActions.addAction(self.actionReprioritize) self.menuActions.addSeparator() self.menuActions.addAction(self.actionRemoveSelected) self.menuActions.addAction(self.actionIgnoreSelected) self.menuActions.addAction(self.actionMakeSelectedReference) self.menuActions.addSeparator() self.menuActions.addAction(self.actionOpenSelected) self.menuActions.addAction(self.actionRevealSelected) self.menuActions.addAction(self.actionInvokeCustomCommand) self.menuActions.addAction(self.actionRenameSelected) self.menuMark.addAction(self.actionMarkAll) self.menuMark.addAction(self.actionMarkNone) self.menuMark.addAction(self.actionInvertMarking) self.menuMark.addAction(self.actionMarkSelected) self.menuView.addAction(self.actionPowerMarker) self.menuView.addAction(self.actionDelta) self.menuView.addSeparator() self.menuView.addAction(self.actionDetails) self.menuView.addAction(self.app.actionIgnoreList) self.menuView.addAction(self.app.actionPreferences) self.menuHelp.addAction(self.app.actionShowHelp) self.menuHelp.addAction(self.app.actionOpenDebugLog) self.menuHelp.addAction(self.app.actionAbout) self.menuFile.addAction(self.actionSaveResults) self.menuFile.addAction(self.actionExportToHTML) self.menuFile.addAction(self.actionExportToCSV) self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionQuit) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuMark.menuAction()) self.menubar.addAction(self.menuActions.menuAction()) self.menubar.addAction(self.menuColumns.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) # Columns menu menu = self.menuColumns self._column_actions = [] for index, (display, visible) in enumerate(self.app.model.result_table.columns.menu_items()): action = menu.addAction(display) action.setCheckable(True) action.setChecked(visible) action.item_index = index self._column_actions.append(action) menu.addSeparator() action = menu.addAction(tr("Reset to Defaults")) action.item_index = -1 # Action menu actionMenu = QMenu(tr("Actions"), self.menubar) actionMenu.addAction(self.actionDeleteMarked) actionMenu.addAction(self.actionMoveMarked) actionMenu.addAction(self.actionCopyMarked) actionMenu.addAction(self.actionRemoveMarked) actionMenu.addSeparator() actionMenu.addAction(self.actionRemoveSelected) actionMenu.addAction(self.actionIgnoreSelected) actionMenu.addAction(self.actionMakeSelectedReference) actionMenu.addSeparator() actionMenu.addAction(self.actionOpenSelected) actionMenu.addAction(self.actionRevealSelected) actionMenu.addAction(self.actionInvokeCustomCommand) actionMenu.addAction(self.actionRenameSelected) self.actionActions.setMenu(actionMenu) self.actionsButton.setMenu(self.actionActions.menu()) def _setupUi(self): self.setWindowTitle(tr("{} Results").format(self.app.NAME)) self.resize(630, 514) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(0) self.actionsButton = QPushButton(tr("Actions")) self.detailsButton = QPushButton(tr("Details")) self.dupesOnlyCheckBox = QCheckBox(tr("Dupes Only")) self.deltaValuesCheckBox = QCheckBox(tr("Delta Values")) self.searchEdit = SearchEdit() self.searchEdit.setMaximumWidth(300) self.horizontalLayout = horizontalWrap([self.actionsButton, self.detailsButton, self.dupesOnlyCheckBox, self.deltaValuesCheckBox, None, self.searchEdit, 8]) self.horizontalLayout.setSpacing(8) self.verticalLayout.addLayout(self.horizontalLayout) self.resultsView = ResultsView(self.centralwidget) self.resultsView.setSelectionMode(QAbstractItemView.ExtendedSelection) self.resultsView.setSelectionBehavior(QAbstractItemView.SelectRows) self.resultsView.setSortingEnabled(True) self.resultsView.verticalHeader().setVisible(False) h = self.resultsView.horizontalHeader() h.setHighlightSections(False) h.setSectionsMovable(True) h.setStretchLastSection(False) h.setDefaultAlignment(Qt.AlignLeft) self.verticalLayout.addWidget(self.resultsView) self.setCentralWidget(self.centralwidget) self._setupActions() self._setupMenu() self.statusbar = QStatusBar(self) self.statusbar.setSizeGripEnabled(True) self.setStatusBar(self.statusbar) self.statusLabel = QLabel(self) self.statusbar.addPermanentWidget(self.statusLabel, 1) if self.app.prefs.resultWindowIsMaximized: self.setWindowState(self.windowState() | Qt.WindowMaximized) else: if self.app.prefs.resultWindowRect is not None: self.setGeometry(self.app.prefs.resultWindowRect) else: moveToScreenCenter(self) #--- Private def _update_column_actions_status(self): # Update menu checked state menu_items = self.app.model.result_table.columns.menu_items() for action, (display, visible) in zip(self._column_actions, menu_items): action.setChecked(visible) #--- Actions def actionsTriggered(self): self.actionsButton.showMenu() def addToIgnoreListTriggered(self): self.app.model.add_selected_to_ignore_list() def copyTriggered(self): self.app.model.copy_or_move_marked(True) def deleteTriggered(self): self.app.model.delete_marked() def deltaTriggered(self, state=None): # The sender can be either the action or the checkbox, but both have a isChecked() method. self.resultsModel.delta_values = self.sender().isChecked() self.actionDelta.setChecked(self.resultsModel.delta_values) self.deltaValuesCheckBox.setChecked(self.resultsModel.delta_values) def detailsTriggered(self): self.app.show_details() def markAllTriggered(self): self.app.model.mark_all() def markInvertTriggered(self): self.app.model.mark_invert() def markNoneTriggered(self): self.app.model.mark_none() def markSelectedTriggered(self): self.app.model.toggle_selected_mark_state() def moveTriggered(self): self.app.model.copy_or_move_marked(False) def openTriggered(self): self.app.model.open_selected() def powerMarkerTriggered(self, state=None): # see deltaTriggered self.resultsModel.power_marker = self.sender().isChecked() self.actionPowerMarker.setChecked(self.resultsModel.power_marker) self.dupesOnlyCheckBox.setChecked(self.resultsModel.power_marker) def preferencesTriggered(self): self.app.show_preferences() def removeMarkedTriggered(self): self.app.model.remove_marked() def removeSelectedTriggered(self): self.app.model.remove_selected() def renameTriggered(self): index = self.resultsView.selectionModel().currentIndex() # Our index is the current row, with column set to 0. Our filename column is 1 and that's # what we want. index = index.sibling(index.row(), 1) self.resultsView.edit(index) def reprioritizeTriggered(self): dlg = PrioritizeDialog(self, self.app) result = dlg.exec() if result == QDialog.Accepted: dlg.model.perform_reprioritization() def revealTriggered(self): self.app.model.reveal_selected() def saveResultsTriggered(self): title = tr("Select a file to save your results to") files = tr("dupeGuru Results (*.dupeguru)") destination, chosen_filter = QFileDialog.getSaveFileName(self, title, '', files) if destination: if not destination.endswith('.dupeguru'): destination = '{}.dupeguru'.format(destination) self.app.model.save_as(destination) self.app.recentResults.insertItem(destination) #--- Events def appWillSavePrefs(self): prefs = self.app.prefs prefs.resultWindowIsMaximized = self.isMaximized() prefs.resultWindowRect = self.geometry() def columnToggled(self, action): index = action.item_index if index == -1: self.app.model.result_table.columns.reset_to_defaults() self._update_column_actions_status() else: visible = self.app.model.result_table.columns.toggle_menu_item(index) action.setChecked(visible) def contextMenuEvent(self, event): self.actionActions.menu().exec_(event.globalPos()) def resultsDoubleClicked(self, modelIndex): self.app.model.open_selected() def resultsSpacePressed(self): self.app.model.toggle_selected_mark_state() def searchChanged(self): self.app.model.apply_filter(self.searchEdit.text())
class Dimili(QMainWindow): def baslat(self, anaPencere): anaPencere.resize(600, 400) anaPencere.setWindowTitle("Dimili-Türkçe Sözlük") anaPencere.setFixedSize(600,400) icon =QIcon() icon.addPixmap(QPixmap("Dictionary.png"),QIcon.Normal,QIcon.Off) anaPencere.setWindowIcon(icon) zemin=QWidget(anaPencere) zemin.setGeometry(QRect(0,30,600,390)) zemin.setStyleSheet("background-color:rgb(167, 196, 233);") self.araKutu = QLineEdit(anaPencere) self.araKutu.setGeometry(QRect(10, 80, 200, 20)) self.araKutu.textChanged.connect(self.benzerKelimeler) self.kelimeGir = QLabel("Kelimeler:",anaPencere) self.kelimeGir.setGeometry(QRect(10, 110, 141, 21)) self.kelimeGor = QLabel("Kelime Ara",anaPencere) self.kelimeGor.setGeometry(QRect(10, 30, 91, 16)) self.harfGrup=QButtonGroup(anaPencere) aharf=QPushButton("â",anaPencere) aharf.setGeometry(QRect(10,50,25,25)) eharf=QPushButton("é",anaPencere) eharf.setGeometry(QRect(30,50,25,25)) self.DilGrup=QButtonGroup(anaPencere) self.Dil1 = QPushButton("Zazaca-Türkçe",anaPencere) self.Dil1.setGeometry(QRect(230, 80, 91, 23)) self.Dil1.setCheckable(True) self.Dil1.setAutoExclusive(True) self.Dil1.setChecked(True) self.Dil1.setStyleSheet("background-color: rgb(102, 255, 0);") self.Dil2 = QPushButton("Türkçe-Zazaca",anaPencere) self.Dil2.setGeometry(QRect(330, 80, 91, 23)) self.Dil2.setCheckable(True) self.Dil2.setAutoExclusive(True) self.Dil2.setStyleSheet("background-color: rgb(255, 94, 105);") self.DilGrup.addButton(self.Dil1,1) self.DilGrup.addButton(self.Dil2,2) self.DilGrup.buttonClicked[int].connect(self.dilSecme) self.kelimeListesi=QListWidget(anaPencere) self.kelimeListesi.setGeometry(QRect(10, 130, 191, 231)) self.kelimeListesi.itemClicked.connect(self.kelimeAcikla) self.kelimeAnlam = QLabel("Kelimenin Anlamı:",anaPencere) self.kelimeAnlam.setGeometry(QRect(230, 110, 131, 21)) self.cumleList1 = QListWidget(anaPencere) self.cumleList1.setGeometry(QRect(230, 130, 351, 51)) self.ornekCumle1 = QLabel("Örnek Zazaca Cümle:",anaPencere) self.ornekCumle1.setGeometry(QRect(230, 200, 101, 21)) self.cumleList2 = QListWidget(anaPencere) self.cumleList2.setGeometry(QRect(230, 220, 351, 51)) self.ornekCumle2 = QLabel("Örnek Türkçe Cümle:",anaPencere) self.ornekCumle2.setGeometry(QRect(230, 290, 111, 16)) self.cumleList3 = QListWidget(anaPencere) self.cumleList3.setGeometry(QRect(230, 310, 351, 51)) self.anaMenu = QMenuBar(anaPencere) self.anaMenu.setGeometry(QRect(0, 0, 600, 21)) self.menuDosya = QMenu("Dosya",self.anaMenu) self.menuDuzenle = QMenu("Düzenle",self.anaMenu) self.menuYardim = QMenu("Yardım",self.anaMenu) anaPencere.setMenuBar(self.anaMenu) self.durum = QStatusBar(zemin) anaPencere.setStatusBar(self.durum) self.durum.setStyleSheet("background-color:white") self.durum.showMessage("Hazır") self.cikis= QAction(QIcon("Exit.ico"),"&Çıkış",anaPencere) self.cikis.setShortcut("Ctrl+X") self.cikis.triggered.connect(anaPencere.close) self.actionHakkinda = QAction("Hakkında",anaPencere) self.actionHakkinda.triggered.connect(self.hakkinda) self.actionSecenekler = QAction("Seçenekler",anaPencere) self.menuDosya.addAction(self.cikis) self.menuDuzenle.addAction(self.actionSecenekler) self.menuYardim.addAction(self.actionHakkinda) self.anaMenu.addAction(self.menuDosya.menuAction()) self.anaMenu.addAction(self.menuDuzenle.menuAction()) self.anaMenu.addAction(self.menuYardim.menuAction()) def kelimeAcikla(self): if self.DilGrup.checkedId()==1: self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() itemtext= [str(x.text()) for x in self.kelimeListesi.selectedItems()] for it in itemtext: itemtext=it self.im.execute("select Tur from DimTur where Zazaca=?",[itemtext]) turliste=[tur[0] for tur in self.im.fetchall()] for tura in turliste: turliste=tura self.im.execute("select Turkce from DimTur where Zazaca=?",[itemtext]) turkAnlam=[tur[0] for tur in self.im.fetchall()] for tr in turkAnlam: self.cumleList1.addItem(itemtext+"("+turliste+")"+" : "+tr) self.im.execute("select OrnekZazacaCumle from DimTur where Zazaca=?",[itemtext]) ornekZaza=[zaza[0] for zaza in self.im.fetchall()] for za in ornekZaza: ornekZaza=za self.cumleList2.addItem(ornekZaza) self.im.execute("select OrnekTurkceCumle from DimTur where Zazaca=?",[itemtext]) ornekTurk=[turk[0] for turk in self.im.fetchall()] for orn in ornekTurk: ornekTurk=orn self.cumleList3.addItem(ornekTurk) if self.DilGrup.checkedId()==2: self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() itemtext= [str(x.text()) for x in self.kelimeListesi.selectedItems()] for it in itemtext: itemtext=it self.im.execute("select Tur from DimTur where Turkce=?",[itemtext]) turliste=[tur[0] for tur in self.im.fetchall()] for tura in turliste: turliste=tura self.im.execute("select Zazaca from DimTur where Turkce=?",[itemtext]) zazaAnlam=[tur[0] for tur in self.im.fetchall()] for tr in zazaAnlam: self.cumleList1.addItem(itemtext+"("+turliste+")"+" : "+tr) self.im.execute("select OrnekZazacaCumle from DimTur where Turkce=?",[itemtext]) ornekTurk=[turk[0] for turk in self.im.fetchall()] for orn in ornekTurk: ornekTurk=orn self.cumleList2.addItem(ornekTurk) self.im.execute("select OrnekTurkceCumle from DimTur where Turkce=?",[itemtext]) ornekZaza=[zaza[0] for zaza in self.im.fetchall()] for za in ornekZaza: ornekZaza=za self.cumleList3.addItem(ornekZaza) def benzerKelimeler(self): if self.DilGrup.checkedId()==1: self.VT=sqlite3.connect("DimiliVT.sqlite") self.im=self.VT.cursor() self.kelimeListesi.clear() kelime=self.araKutu.text() if kelime=="" or kelime==None: self.kelimeListesi.clear() else: self.im.execute("select Zazaca from DimTur where Zazaca like ? order by Zazaca ",[kelime+'%']) zazaListe=[za[0] for za in self.im.fetchall()] for i in zazaListe: self.kelimeListesi.addItem(i) if self.DilGrup.checkedId()==2: self.VT=sqlite3.connect("DimiliVT.sqlite") self.im=self.VT.cursor() kelime=self.araKutu.text() self.kelimeListesi.clear() if kelime=="" or kelime==None: self.kelimeListesi.clear() else: self.im.execute("select Turkce from DimTur where Turkce like ? ",[kelime+'%']) turkListe=[tu[0] for tu in self.im.fetchall()] for i in turkListe: self.kelimeListesi.addItem(i) def dilSecme(self,ind): if ind==1: self.araKutu.setText("") self.kelimeListesi.clear() self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() self.Dil1.setStyleSheet("background:#66FF00") self.Dil2.setStyleSheet("background-color:#E41841") if ind==2: self.araKutu.setText("") self.kelimeListesi.clear() self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() self.Dil2.setStyleSheet("background:#66FF00") self.Dil1.setStyleSheet("background-color:#E41841") def hakkinda(self): QMessageBox.about(self, "Program Hakkında", "Bu program <b>bla bla</b> tarafından programlanmıştır. 2015")