Esempio n. 1
0
    def __init__(self, settings, *args, **kwargs):
        super().__init__(*args, **kwargs)

        layout = QGridLayout(self)
        #layout.setContentsMargins(0, 0, 0, 0)

        settings_tabs = QTabWidget()
        layout.addWidget(settings_tabs)

        form = 'Gaussian'
        self.method = MethodOption(settings, form)
        settings_tabs.addTab(self.method, "Method")

        self.basis = BasisWidget(settings, form)
        settings_tabs.addTab(self.basis, "Basis Sets")
        #menu stuff
        menu = QMenuBar()

        self.presets_menu = menu.addMenu("Presets")

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)

        self.settings = settings
        self.presets = {}
        self.presets['Gaussian'] = loads(self.settings.gaussian_presets)
        self.presets['ORCA'] = loads(self.settings.orca_presets)
        self.presets['Psi4'] = loads(self.settings.psi4_presets)

        self.refresh_presets()
Esempio n. 2
0
class Ui_Dialog(object):
    def setupUi(self, Dialog):
        def hello(self):
            print("hello")

        Dialog.setObjectName("Dialog")
        Dialog.setWindowModality(QtCore.Qt.ApplicationModal)
        Dialog.resize(1280, 840)

        exitAction = QAction(QIcon('exit.png'), 'Exit', parent=Dialog)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(qApp.quit)

        SaveAction = QAction(QIcon('save.png'), 'Save', parent=Dialog)
        SaveAction.setShortcut('Ctrl+S')
        SaveAction.setStatusTip('Save')
        SaveAction.triggered.connect(hello)

        Anti_Action = QAction(QIcon('Anti.png'),
                              'Anti-Forensic Tool Execution Trace',
                              parent=Dialog)
        Anti_Action.setStatusTip('Anti-Forensic Tool Execution Trace')
        Anti_Action.triggered.connect(hello)

        Mal_Action = QAction(QIcon('mal.png'),
                             'Malicious File Execution Trace',
                             parent=Dialog)
        Mal_Action.setStatusTip('Malicious File Execution Trace')
        Mal_Action.triggered.connect(hello)

        Freq_Action = QAction(QIcon('freq.png'),
                              'Freqently Used File Trace',
                              parent=Dialog)
        Freq_Action.setStatusTip('Freqently Used File Trace')
        Freq_Action.triggered.connect(hello)

        Cont_Action = QAction(QIcon('cont.png'),
                              'Continuous File Execution Trace',
                              parent=Dialog)
        Cont_Action.setStatusTip('Continuous File Execution Trace')
        Cont_Action.triggered.connect(hello)

        Dele_Action = QAction(QIcon('dele.png'),
                              'Currently Deleted Executable Trace',
                              parent=Dialog)
        Dele_Action.setStatusTip('Currently Deleted Executable Trace')
        Dele_Action.triggered.connect(Defile)

        self.menubar = QMenuBar(Dialog)
        self.menubar.setNativeMenuBar(False)
        self.filemenu = self.menubar.addMenu('&File')
        self.filemenu.addAction(exitAction)
        self.filemenu.addAction(SaveAction)
        self.toolmenu = self.menubar.addMenu('&Tool')
        self.toolmenu.addAction(Anti_Action)
        self.toolmenu.addAction(Freq_Action)
        self.toolmenu.addAction(Cont_Action)
        self.toolmenu.addAction(Dele_Action)
        self.toolmenu.addAction(Mal_Action)
Esempio n. 3
0
def _create_menu_bar(parent):
    """Create a menu bar.

    The menu bar is expected to behave consistently
    for every operating system since `setNativeMenuBar(False)`
    is called by default and therefore lifetime and ownership can
    be tested.
    """
    menu_bar = QMenuBar(parent=parent)
    menu_bar.setNativeMenuBar(False)
    if parent is not None:
        parent.setMenuBar(menu_bar)
    return menu_bar
Esempio n. 4
0
class _QtMenuBar(_AbstractMenuBar):
    def _menu_initialize(self, window):
        self._menus = dict()
        self._menu_actions = dict()
        self.menu_bar = QMenuBar()
        self.menu_bar.setNativeMenuBar(False)
        window.setMenuBar(self.menu_bar)

    def _menu_add_submenu(self, name, desc):
        self._menus[name] = self.menu_bar.addMenu(desc)

    def _menu_add_button(self, menu_name, name, desc, func):
        menu = self._menus[menu_name]
        self._menu_actions[name] = menu.addAction(desc, func)
Esempio n. 5
0
    def setup_menubar(self):
        menuBar = QMenuBar(self)
        menuBar.setNativeMenuBar(False)
        self.setMenuBar(menuBar)
        leagueMenu = menuBar.addMenu("&League")
        years = [2021, 2020, 2019, 2018]
        fantasy_games = ['nhl', 'nfl']

        for year in years:
            year_menu = leagueMenu.addMenu(str(year))
            for game in fantasy_games:
                game_menu = year_menu.addMenu(game)
                gm = yfa.Game(self.oauth, game)
                ids = gm.league_ids(year)
                for id in ids:
                    lg = gm.to_league(id)
                    lg_action = QAction(lg.settings()['name'], self)
                    lg_action.league_id = id
                    lg_action.game_type = game
                    lg_action.year = year
                    game_menu.addAction(lg_action)
                    game_menu.triggered[QAction].connect(self.league_selected)
Esempio n. 6
0
class Ui_MainWindow(object):
    def text_inputChanged(self):
        self.timer_wait_to_refresh.start(1500)

    def refresh_output_when_timeout(self):
        self.timer_wait_to_refresh.stop()
        a_input = self.text_input.toPlainText()
        print('\ninputed data\n' + a_input)
        cmd = 'wbxml2xml'
        try:
            ishex = int(a_input[:5], 16)
            finput = open(dirScript + '/input_file', 'wb')
            a_input = "".join(a_input.split())
            a = [a_input[i:i + 2] for i in range(0, len(a_input), 2)]
            for aa in a:
                finput.write(binascii.unhexlify(aa))
            finput.close()
        except Exception as e:
            finput = open(dirScript + '/input_file', 'w')
            finput.writelines(a_input)
            finput.close()
            cmd = 'xml2wbxml'
        fullcmd = 'export PATH=/usr/local/bin:$PATH;' + cmd + ' -o ' + dirScript + '/output_file ' + dirScript + '/input_file'
        output = subprocess.getstatusoutput(fullcmd)
        self.label_parse_result.setText(cmd) if output[0] == 0 else self.label_parse_result.setText(cmd + " failed")
        if output[0] == 0:
            if cmd == "xml2wbxml":
                try:
                    with open(dirScript + '/output_file', "rb") as binary_file:
                        # Read the whole file at once
                        data = binary_file.read()
                        chs = ""
                        for ch in data:
                            chs += "{0:02x}".format(ch)
                        print('\nconverted wbxml\n' + chs)
                        self.text_output.setText(chs)
                except Exception as e:
                    print(str(e))
                    self.text_output.setText('Exception:\n' + str(e))
            else:
                try:
                    with open(dirScript + '/output_file', 'r') as xml_file:
                        data = xml_file.read()
                        print('\nconverted xml\n' + data)
                        self.text_output.setPlainText(data)
                except Exception as e:
                    print(str(e))
                    self.text_output.setText('Exception:\n' + str(e))
        else:
            self.text_output.setText(output[1])

    def setupUi(self, main_window):
        main_window.setObjectName("main_window")
        main_window.resize(1024, 600)
        # self.centralwidget = QtWidgets.QWidget(main_window)
        # self.centralwidget.setObjectName("centralwidget")
        # main_window.setCentralWidget(self.centralwidget)
        font = QFont('Roboto')
        font.setPointSize(16)

        fontmono = QFont('SF Mono')

        self.menubar = QMenuBar(main_window)
        if platform.uname().system == 'Darwin':
            self.menubar.setNativeMenuBar(True)
        self.menubar.setFont(font)
        self.menubar.setObjectName("menubar")
        main_window.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(main_window)
        self.statusbar.setObjectName("statusbar")
        main_window.setStatusBar(self.statusbar)

        self.subtitle = QHBoxLayout()
        self.label_input = QLabel()
        self.label_input.setFont(font)
        self.label_input.setAlignment(Qt.AlignCenter)
        self.label_input.setText("copy paste XML/WBXML here")

        self.label_parse_result = QLabel()
        self.label_parse_result.setFont(font)
        self.label_parse_result.setAlignment(Qt.AlignCenter)
        self.label_parse_result.setText("converted output")

        self.subtitle.addWidget(self.label_input)
        self.subtitle.addWidget(self.label_parse_result)

        self.text_input = QTextEdit()
        self.text_input.setAcceptRichText(False)
        self.text_input.setFont(fontmono)
        self.text_input.resize(450, 600)
        self.text_input.textChanged.connect(self.text_inputChanged)
        self.timer_wait_to_refresh = QTimer()
        self.timer_wait_to_refresh.setSingleShot(True)
        self.timer_wait_to_refresh.timeout.connect(self.refresh_output_when_timeout)

        self.text_output = QTextEdit()
        self.text_output.setFont(fontmono)
        self.text_output.resize(450, 600)
        self.text_output.setReadOnly(True)
        # self.text_output.setStyleSheet("background-color: gray")

        self.hbox = QHBoxLayout()
        # self.hbox.addStretch()
        self.hbox.addWidget(self.text_input)
        self.hbox.addWidget(self.text_output)
        # self.hbox.addStretch()

        self.vbox = QVBoxLayout()
        self.vbox.addLayout(self.subtitle)
        self.vbox.addLayout(self.hbox)

        self.mainWidget = QWidget()
        self.mainWidget.setLayout(self.vbox)
        main_window.setCentralWidget(self.mainWidget)

        main_window.setWindowTitle('JC WBXML Decoder')

        QtCore.QMetaObject.connectSlotsByName(main_window)
Esempio n. 7
0
class WinApp(QMainWindow, Ui_MainWindow):
    stmt_signal = pyqtSignal(str)

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

        self.setupUi(self)
        self.connButtonBox.button(QDialogButtonBox.Ok).setText("Connect")
        self.runButtonBox.button(QDialogButtonBox.Ok).setText("Run")
        self.tunnelButton.clicked[bool].connect(self.toggle_tunnel)
        self.tunnelWidget.hide()
        self.keyFileButton.clicked.connect(self.choose_keyfile)
        self.clearButton.clicked.connect(self.clear_tunnel)
        self.keyComboBox.activated[str].connect(self.set_key_type)

        self.db_engine = DBEngine()
        self.db_engine.result_signal.connect(self.show_results)
        self.db_engine.progress_signal.connect(self.set_progress)
        self.db_engine.error_signal.connect(self.show_error)
        self.db_engine.msg_signal.connect(self.show_msg)
        self.stmt_signal.connect(self.db_engine.receive_stmt)

        self.db_lite = DBLite()
        self.tunnel = Tunnel()
        self.tunnel_keyfile = ""
        self.data_schema = []
        self.settings = QSettings()
        self.restore_settings()

        history = self.db_lite.history()
        self.historyMenuBar = QMenuBar(self.sqlWidget)
        self.historyMenuBar.setNativeMenuBar(False)
        self.historyMenu = self.historyMenuBar.addMenu('     &History   ⇲    ')
        actions = [
            QAction(sql.replace('\n', ' '), self.historyMenu)
            for sql in history
        ]
        for i in range(len(actions)):
            actions[i].triggered.connect(partial(self.use_history, history[i]))
        self.historyMenu.addActions(actions)

        self.history_cache = pylru.lrucache(history_limit, self.remove_action)
        for i in reversed(range(len(history))):
            self.history_cache[history[i]] = {
                KEY_ACTION: actions[i],
                KEY_RESULTS: [],
                KEY_COLUMNS: []
            }

        self.historyMenu.setStyleSheet("""
        QMenu {
            max-width: 1000px;
            font-size: 12px;
        }
        """)
        self.historyMenuBar.setStyleSheet("""
        QMenuBar {
            border: None;
        }
        QMenuBar::item {
            background: #404040;
            color: #ffffff;
            border-radius: 4px;
        }
        QMenuBar::item:selected {
            background: rgba(1, 1, 1, 0.2);;
            color: #404040;
            border-radius: 4px;
        }
        """)
        self.sqlWidgetLayout.insertWidget(0, self.historyMenuBar)

        self.connButtonBox.accepted.connect(self.connect)
        self.connButtonBox.rejected.connect(self.disconnect)
        self.runButtonBox.accepted.connect(self.run)
        self.runButtonBox.rejected.connect(self.cancel)
        self.tablesWidget.itemDoubleClicked.connect(self.get_meta)
        self.tablesWidget.itemExpanded.connect(self.get_meta)

        self.progressBar = QProgressBar()
        self.statusbar.addPermanentWidget(self.progressBar)
        self.progressBar.setValue(100)
        QApplication.processEvents()

        self.highlight = syntax.PrestoHighlighter(self.sqlEdit)

        self.dataWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.dataWidget.customContextMenuRequested.connect(
            self.show_table_context_menu)
        self.dataWidget.horizontalHeader().setStretchLastSection(False)
        self.dataWidget.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)

        self.schemaView.header().setStretchLastSection(False)
        self.schemaView.header().setSectionResizeMode(
            QHeaderView.ResizeToContents)

        self.runButtonBox.button(
            QDialogButtonBox.Ok).setShortcut("Ctrl+Return")

        self.completer = SQLCompleter(self)
        self.sqlEdit.setCompleter(self.completer)

        self.set_key_type(self.keyComboBox.currentText())
        self.sqlEdit.setFocus()

    def connect(self):
        self.tablesWidget.clear()
        self.schemaView.clear()
        try:
            if self.serverEdit.text().strip() and self.gatewayEdit.text(
            ).strip() and self.tunnelUserEdit.text().strip():
                self.statusbar.showMessage('Starting tunnel')
                QApplication.processEvents()
                self.tunnel.start_tunnel(
                    self.serverEdit.text().strip(),
                    self.gatewayEdit.text().strip(),
                    self.tunnelUserEdit.text().strip(),
                    self.keyComboBox.currentText() == 'KeyFile',
                    self.tunnel_keyfile, self.pwdLineEdit.text(),
                    self.urlEdit.text().strip())

            self.statusbar.showMessage('Connecting')
            QApplication.processEvents()
            self.db_engine.connect(self.urlEdit.text().strip(),
                                   self.userEdit.text().strip())
            self.statusbar.showMessage('Fetching db info')
            QApplication.processEvents()

            dbs = self.db_engine.dbs()
            for db in dbs:
                db_item = QTreeWidgetItem([db])
                db_item.setChildIndicatorPolicy(QTreeWidgetItem.ShowIndicator)
                self.tablesWidget.addTopLevelItem(db_item)
            self.completer.addItems(dbs)
            self.statusbar.showMessage('Connected')

        except Exception as err:
            QMessageBox.critical(self, "Error", str(err))
            self.db_engine.close()
            self.statusbar.showMessage('Disconnected')

    def disconnect(self):
        self.db_engine.close()
        self.tunnel.stop_tunnel()
        self.schemaView.clear()
        self.tablesWidget.clear()
        self.statusbar.showMessage('Disconnected')

    def get_meta(self, item):
        try:
            if item.parent():
                columns = self.db_engine.columns(item.parent().text(0),
                                                 item.text(0))
                self.set_columns(columns)
                self.completer.addItems([column[0] for column in columns])
            else:
                if item.childCount() <= 0:
                    tables = self.db_engine.tables(item.text(0))
                    item.addChildren(
                        [QTreeWidgetItem([table]) for table in tables])
                    self.completer.addTreeItem(item)
        except Exception as err:
            QMessageBox.critical(self, "Error", str(err))

    def set_columns(self, columns):
        try:
            self.schemaView.clear()
            for column in columns:
                column_item = self.type_tree(column[0],
                                             type_parser.parse(column[1]))
                self.schemaView.addTopLevelItem(column_item)
            self.schemaView.expandToDepth(2)
            for j in range(self.schemaView.columnCount()):
                self.schemaView.resizeColumnToContents(j)
        except Exception as err:
            QMessageBox.critical(self, "Error", str(err))

    def run(self):
        self.dataWidget.setRowCount(0)
        self.dataWidget.setColumnCount(0)
        try:
            self.stmt_signal.emit(self.sqlEdit.toPlainText().strip().replace(
                ';', ''))
            self.db_engine.start()
        except Exception as err:
            QMessageBox.critical(self, "Error", str(err))

    def show_results(self, results, columns, sql, save=True):
        try:
            num_cols = len(columns)
            num_rows = len(results)
            self.dataWidget.setRowCount(num_rows)
            self.dataWidget.setColumnCount(num_cols)
            for i in range(num_rows):
                for j in range(num_cols):
                    self.dataWidget.setItem(
                        i, j, QTableWidgetItem(str(results[i][j])))
            self.dataWidget.resizeColumnsToContents()
            for j in range(num_cols):
                header_label = columns[j][0]
                # header_width = self.fm.width(header_label)
                # if header_width > self.dataWidget.columnWidth(j):
                #     self.dataWidget.setColumnWidth(j, header_width)
                self.dataWidget.setHorizontalHeaderItem(
                    j, QTableWidgetItem(header_label))
            self.data_schema = [column[1] for column in columns]
            if not columns and not results:
                self.dataWidget.setColumnCount(1)
                self.dataWidget.setHorizontalHeaderItem(
                    0, QTableWidgetItem("Empty Result"))
            if save:
                self.save_history(sql, results, columns)
        except Exception as err:
            QMessageBox.critical(self, "Error", str(err))
        finally:
            self.statusbar.showMessage('Finished')

    def cancel(self):
        self.db_engine.cancel()

    def set_progress(self, progress):
        self.progressBar.setValue(progress)
        QApplication.processEvents()

    def save_history(self, sql, results, columns):
        if sql not in self.history_cache:
            action = QAction(sql.replace('\n', ' '), self.historyMenu)
            action.triggered.connect(partial(self.use_history, sql))
            self.history_cache[sql] = {
                KEY_ACTION: action,
                KEY_RESULTS: results,
                KEY_COLUMNS: columns
            }
        else:
            action = self.history_cache[sql][KEY_ACTION]
            self.historyMenu.removeAction(action)
            if len(results) * len(columns) <= CACHE_LIMIT:
                self.history_cache[sql][KEY_RESULTS] = results
                self.history_cache[sql][KEY_COLUMNS] = columns
            else:
                self.history_cache[sql][KEY_RESULTS] = []
                self.history_cache[sql][KEY_COLUMNS] = [
                    ("results too large to cache", "varchar")
                ]
        self.historyMenu.insertAction(
            self.historyMenu.actions()[0] if
            (self.historyMenu.actions()) else None, action)
        self.db_lite.upsert(sql)

    def use_history(self, sql):
        self.sqlEdit.setText(sql)
        QApplication.processEvents()
        cached = self.history_cache[sql]
        self.db_engine.result_signal.emit(cached[KEY_RESULTS],
                                          cached[KEY_COLUMNS], sql, False)
        self.statusbar.showMessage("Loaded cached history")

    def remove_action(self, sql, cached):
        self.historyMenu.removeAction(cached[KEY_ACTION])

    def show_table_context_menu(self, position):
        col = self.dataWidget.columnAt(position.x())
        dialog = QDialog(self, Qt.Popup)
        schema_view = QTreeWidget(dialog)
        schema_view.headerItem().setText(0, "Field")
        schema_view.headerItem().setText(1, "Type")
        root = type_parser.parse(self.data_schema[col])
        schema_tree = self.type_tree(
            self.dataWidget.horizontalHeaderItem(col).text(), root)
        schema_view.addTopLevelItem(schema_tree)
        schema_view.expandToDepth(2)
        schema_view.header().setStretchLastSection(False)
        schema_view.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContentsOnFirstShow)
        schema_view.header().setSectionResizeMode(QHeaderView.ResizeToContents)
        schema_view.setMinimumHeight(30)
        schema_view.setMaximumHeight(400)
        schema_view.adjustSize()
        schema_view.setHeaderHidden(True)

        dialog.move(
            self.dataWidget.mapToGlobal(position) +
            QPoint(dialog.width() / 5 * 2,
                   dialog.height() + 5))
        dialog.adjustSize()
        dialog.show()

    def type_tree(self, name, root):
        if root.children[0].data == 'primitive_type':
            return QTreeWidgetItem([name, root.children[0].children[0].value])
        elif root.children[0].data == 'row_type':
            root_widget = QTreeWidgetItem([name, 'row'])
            for i in range(len(root.children[0].children) // 2):
                name = root.children[0].children[i * 2].value
                child_type = root.children[0].children[i * 2 + 1]
                root_widget.addChild(self.type_tree(name, child_type))
            return root_widget
        elif root.children[0].data == 'array_type':
            if root.children[0].children[0].children[
                    0].data == 'primitive_type':
                return QTreeWidgetItem([
                    name, 'array(' +
                    root.children[0].children[0].children[0].children[0].value
                    + ')'
                ])
            else:
                root_widget = QTreeWidgetItem([name, 'array(row)'])
                for i in range(
                        len(root.children[0].children[0].children[0].children)
                        // 2):
                    name = root.children[0].children[0].children[0].children[
                        i * 2].value
                    child_type = root.children[0].children[0].children[
                        0].children[i * 2 + 1]
                    root_widget.addChild(self.type_tree(name, child_type))
                return root_widget

        elif root.children[0].data == 'map_type':
            root_widget = QTreeWidgetItem([name, 'map'])
            key = self.type_tree('_key', root.children[0].children[0])
            value = self.type_tree('_value', root.children[0].children[1])
            root_widget.addChildren([key, value])
            return root_widget
        else:
            pass

    def toggle_tunnel(self, pressed):
        if pressed:
            self.tunnelWidget.show()
            self.repaint()
        else:
            self.tunnelWidget.hide()

    def choose_keyfile(self):
        file_name, _ = QFileDialog.getOpenFileName(self, "Choose Key File",
                                                   QDir.homePath() + "/.ssh",
                                                   "All Files (*)")
        if file_name:
            self.tunnel_keyfile = file_name
            self.keyFileButton.setText(file_name.split('/')[-1])

    def clear_tunnel(self):
        self.tunnel_keyfile = None
        self.keyFileButton.setText("Choose Key File...")
        self.serverEdit.clear()
        self.gatewayEdit.clear()
        self.tunnelUserEdit.clear()
        self.pwdLineEdit.clear()

    def close_all(self):
        self.save_settings()
        self.db_engine.close()
        self.tunnel.stop_tunnel()

    def restore_settings(self):
        self.urlEdit.setText(self.settings.value(URL, ""))
        self.userEdit.setText(self.settings.value(USER, ""))
        self.serverEdit.setText(self.settings.value(SERVER, ""))
        self.gatewayEdit.setText(self.settings.value(GATEWAY, ""))
        self.tunnelUserEdit.setText(self.settings.value(TUNNEL_USER, ""))
        self.tunnel_keyfile = self.settings.value(KEYFILE, "")
        if self.tunnel_keyfile:
            self.keyFileButton.setText(self.tunnel_keyfile.split('/')[-1])
        self.pwdLineEdit.setText(self.settings.value(TUNNEL_PWD, ""))
        self.keyComboBox.setCurrentText(self.settings.value(
            KEYTYPE, "KeyFile"))

    def save_settings(self):
        self.settings.setValue(URL, self.urlEdit.text().strip())
        self.settings.setValue(USER, self.userEdit.text().strip())
        self.settings.setValue(SERVER, self.serverEdit.text().strip())
        self.settings.setValue(GATEWAY, self.gatewayEdit.text().strip())
        self.settings.setValue(TUNNEL_USER, self.tunnelUserEdit.text().strip())
        self.settings.setValue(KEYFILE, self.tunnel_keyfile)
        self.settings.setValue(KEYTYPE, self.keyComboBox.currentText())
        self.settings.setValue(TUNNEL_PWD, self.pwdLineEdit.text())
        self.settings.sync()

    def show_error(self, error):
        QMessageBox.critical(self, "Error", error)

    def show_msg(self, msg):
        self.statusbar.showMessage(msg)

    def set_key_type(self, key_type):
        if key_type == 'KeyFile':
            self.pwdLineEdit.hide()
            self.keyFileButton.show()
        else:
            self.keyFileButton.hide()
            self.pwdLineEdit.show()
class Window(QWidget):
    def __init__(self):
        # other lines above
        QWidget.__init__(self)
        self.resize(450, 250)
        self.setWindowTitle('Tax Calculation')
        self.layout = QGridLayout()
        self.setLayout(self.layout)

        # This is for filename
        self.file_name = ''

        # Add status bar
        self.statusbar = QStatusBar()

        # Add MenuBar
        self.menubar = QMenuBar()
        # The default menu is usually in Mac OS,
        # but we don't want to use the one in the OS.
        self.menubar.setNativeMenuBar(False)
        # Display Menu Bar
        self.menubar.show()

        # Add menus
        self.file_menu = self.menubar.addMenu('File')
        self.edit_menu = self.menubar.addMenu('Edit')
        self.help_menu = self.menubar.addMenu('Help')

        self.action_open = QAction('Open', self)
        self.action_open.setShortcut('Ctrl+O')
        self.action_save = QAction('Save', self)
        self.action_save.setShortcut('Ctrl+S')
        self.action_quit = QAction('Quit', self)
        self.action_quit.setShortcut('Ctrl+Q')

        self.action_clear = QAction('Clear All', self)

        self.action_about = QAction('About', self)

        # Link the action to the menu
        self.file_menu.addAction(self.action_open)
        self.file_menu.addAction(self.action_save)
        # To separate (dividing line between open, save, and quit)
        self.file_menu.addSeparator()
        self.file_menu.addAction(self.action_quit)

        self.edit_menu.addAction(self.action_clear)
        self.help_menu.addAction(self.action_about)

        # Empty text editor (make typing)
        self.tax_editor = QTextEdit()

        self.layout.addWidget(self.menubar)
        self.layout.addWidget(self.tax_editor)
        self.layout.addWidget(self.statusbar)

        # Connect to function
        self.action_open.triggered.connect(self.open_text)
        self.action_save.triggered.connect(self.save_text)
        self.action_quit.triggered.connect(self.quit)
        self.action_clear.triggered.connect(self.tax_editor.clear)
        self.action_about.triggered.connect(self.about)

        # If we want to know how many lines we have written
        self.tax_editor.textChanged.connect(self.show_lines)

    # Functions inside the Window class
    def save_text(self):
        # 0pen file and save
        # 0pen dialog, filter as .txt
        # To filter save as text >>
        name, _ = QFileDialog.getSaveFileName(self, 'Save', self.file_name,
                                              'TXT(*.txt)')

        # dialog exists and file is opening
        if name:
            # set file name
            self.file_name = name
            #  'w' >> set to write mode
            file = open(name, 'w')
            # Abis itu we get the text from editor
            text = self.tax_editor.toPlainText()
            # write to file
            file.write(text)
            # close file >> so files that are opened must be closed
            file.close()

    # Similar to the function above (save_text)
    def open_text(self):
        # open file and load
        # open dialog, filter only .txt files, no file name
        name, _ = QFileDialog.getOpenFileName(self, 'Open', '', 'TXT(*.txt)')

        # file exists
        if name:
            # set file name
            self.file_name = name
            # set to read mode
            file = open(name, 'r')

            # process file, read and set to text edit widget
            with file:
                data = file.read()
                enter = data.split('\n')
                self.result_TI = float(enter[0]) - float(enter[1])
                my_num = self.result_TI

                # Python string format thounsand separators
                # To convert float values into commas as thousands separators
                my_ti = '{:,.2f}'.format(my_num)
                agi = '{:,.2f}'.format(float(enter[0]))
                nti = '{:,.2f}'.format(float(enter[1]))

                # The text editor is empty first then fill in the data
                self.tax_editor.setPlainText('')
                self.tax_editor.setPlainText(
                    f'Your Annual Gross Income\t: Rp{agi} \nYour Non-Taxable Income\t: Rp{nti}\nYour Tax Income\t: Rp{str(my_ti)}\nYour Income Tax\t: Rp{str(self.calculate_tax())}'
                )

            # close file
            file.close()

    def calculate_tax(self):
        # Declare Percent as:
        percent_level_1 = 0.05
        percent_level_2 = 0.15
        percent_level_3 = 0.25
        percent_level_4 = 0.30

        # Income Tax Formula:
        tax_level_1 = self.result_TI * percent_level_1
        tax_level_2 = percent_level_1 * 50000000 + (self.result_TI -
                                                    50000000) * percent_level_2
        tax_level_3 = percent_level_1 * 50000000 + percent_level_2 * (
            250000000 - 50000000) + (self.result_TI -
                                     250000000) * percent_level_3
        tax_level_4 = percent_level_1 * 50000000 + percent_level_2 * (
            250000000 - 50000000) + percent_level_3 * (
                500000000 - 250000000) + (self.result_TI -
                                          500000000) * percent_level_4

        # income tax
        if self.result_TI <= 50000000:
            my_num = tax_level_1
            # Python string format thounsand separators
            my_tax = '{:,.2f}'.format(my_num)
            return my_tax

        elif 50000000 < self.result_TI <= 250000000:
            my_num = tax_level_2
            # Python string format thounsand separators
            my_tax = '{:,.2f}'.format(my_num)
            return my_tax

        elif 250000000 < self.result_TI <= 500000000:
            my_num = tax_level_3
            # Python string format thounsand separators
            my_tax = '{:,.2f}'.format(my_num)
            return my_tax

        elif self.result_TI > 500000000:
            my_num = tax_level_4
            # Python string format thounsand separators
            my_tax = '{:,.2f}'.format(my_num)
            return my_tax

    def quit(self):
        # quit application
        QApplication.quit()

    def about(self):
        # show message dengan message box
        msg = QMessageBox()
        msg.setText('This is a dummy Taxpad')
        msg.exec_()

    # Functions inside the Window class
    def show_lines(self):
        # get text
        text = self.tax_editor.toPlainText()
        len_text = len(text.split('\n'))
        self.statusbar.showMessage('Lines: %s' % str(len_text))
Esempio n. 9
0
    def _build_ui(self):
        layout = QVBoxLayout()

        self.file_selector = FilereaderComboBox(self.session)
        self.file_selector.currentIndexChanged.connect(self.fill_table)
        layout.insertWidget(0, self.file_selector, 0)

        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(['Data', 'Value'])
        self.table.horizontalHeader().setStretchLastSection(False)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Interactive)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Stretch)
        self.table.setSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.MinimumExpanding)
        layout.insertWidget(1, self.table, 1)

        self.filter = QLineEdit()
        self.filter.setPlaceholderText("filter data")
        self.filter.textChanged.connect(self.apply_filter)
        self.filter.setClearButtonEnabled(True)
        layout.insertWidget(2, self.filter, 0)

        menu = QMenuBar()

        export = menu.addMenu("&Export")
        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)
        self.copy = copy

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        # comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        # comma.setChecked(self.settings.delimiter == "comma")
        # comma.triggered.connect(lambda *args, delim="comma": self.settings.__setattr__("delimiter", delim))
        # delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        # space = QAction("space", self.tool_window.ui_area, checkable=True)
        # space.setChecked(self.settings.delimiter == "space")
        # space.triggered.connect(lambda *args, delim="space": self.settings.__setattr__("delimiter", delim))
        # delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))

        archive = QAction("Include archive if present",
                          self.tool_window.ui_area,
                          checkable=True)
        archive.triggered.connect(
            lambda checked: setattr(self.settings, "archive", checked))
        archive.triggered.connect(
            lambda *args: self.fill_table(self.file_selector.count() - 1))
        archive.setChecked(self.settings.archive)
        export.addAction(archive)

        unit = menu.addMenu("&Units")

        energy = unit.addMenu("energy")
        hartree = QAction("Hartree", self.tool_window.ui_area, checkable=True)
        hartree.setChecked(self.settings.energy == "Hartree")
        kcal = QAction("kcal/mol", self.tool_window.ui_area, checkable=True)
        kcal.setChecked(self.settings.energy == "kcal/mol")
        kjoule = QAction("kJ/mol", self.tool_window.ui_area, checkable=True)
        kjoule.setChecked(self.settings.energy == "kJ/mol")
        energy.addAction(hartree)
        energy.addAction(kcal)
        energy.addAction(kjoule)

        hartree.triggered.connect(
            lambda *args, val="Hartree": setattr(self.settings, "energy", val))
        hartree.triggered.connect(
            lambda *args: self.fill_table(self.file_selector.count() - 1))
        hartree.triggered.connect(
            lambda *args, action=kcal: action.setChecked(False))
        hartree.triggered.connect(
            lambda *args, action=kjoule: action.setChecked(False))

        kcal.triggered.connect(lambda *args, val="kcal/mol": setattr(
            self.settings, "energy", val))
        kcal.triggered.connect(
            lambda *args: self.fill_table(self.file_selector.count() - 1))
        kcal.triggered.connect(
            lambda *args, action=hartree: action.setChecked(False))
        kcal.triggered.connect(
            lambda *args, action=kjoule: action.setChecked(False))

        kjoule.triggered.connect(
            lambda *args, val="kJ/mol": setattr(self.settings, "energy", val))
        kjoule.triggered.connect(
            lambda *args: self.fill_table(self.file_selector.count() - 1))
        kjoule.triggered.connect(
            lambda *args, action=hartree: action.setChecked(False))
        kjoule.triggered.connect(
            lambda *args, action=kcal: action.setChecked(False))

        mass = unit.addMenu("mass")
        kg = QAction("kg", self.tool_window.ui_area, checkable=True)
        kg.setChecked(self.settings.mass == "kg")
        amu = QAction("Da", self.tool_window.ui_area, checkable=True)
        amu.setChecked(self.settings.mass == "Da")
        mass.addAction(kg)
        mass.addAction(amu)

        kg.triggered.connect(
            lambda *args, val="kg": setattr(self.settings, "mass", val))
        kg.triggered.connect(
            lambda *args: self.fill_table(self.file_selector.count() - 1))
        kg.triggered.connect(
            lambda *args, action=amu: action.setChecked(False))

        amu.triggered.connect(
            lambda *args, val="Da": setattr(self.settings, "mass", val))
        amu.triggered.connect(
            lambda *args: self.fill_table(self.file_selector.count() - 1))
        amu.triggered.connect(
            lambda *args, action=kg: action.setChecked(False))

        rot_const = unit.addMenu("rotational constants")
        temperature = QAction("K", self.tool_window.ui_area, checkable=True)
        temperature.setChecked(self.settings.rot_const == "K")
        hertz = QAction("GHz", self.tool_window.ui_area, checkable=True)
        hertz.setChecked(self.settings.rot_const == "GHz")
        rot_const.addAction(temperature)
        rot_const.addAction(hertz)

        temperature.triggered.connect(
            lambda *args, val="K": setattr(self.settings, "rot_const", val))
        temperature.triggered.connect(
            lambda *args: self.fill_table(self.file_selector.count() - 1))
        temperature.triggered.connect(
            lambda *args, action=hertz: action.setChecked(False))

        hertz.triggered.connect(
            lambda *args, val="GHz": setattr(self.settings, "rot_const", val))
        hertz.triggered.connect(
            lambda *args: self.fill_table(self.file_selector.count() - 1))
        hertz.triggered.connect(
            lambda *args, action=temperature: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)

        if len(self.session.filereader_manager.list()) > 0:
            self.fill_table(0)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Esempio n. 10
0
    def init_gui(self):
        import_tptp_file_action = QAction('&Import TPTP syntax file', self)
        import_tptp_file_action.setShortcut('Ctrl+I')
        import_tptp_file_action.triggered.connect(self.load_tptp_syntax_file)

        import_tptp_file_from_web_action = QAction('&Import TPTP syntax file from web', self)
        import_tptp_file_from_web_action.setShortcut('Ctrl+W')
        import_tptp_file_from_web_action.triggered.connect(self.get_tptp_syntax_from_web)

        save_with_control_file_action = QAction('&Reduce and save TPTP syntax with control file', self)
        save_with_control_file_action.setShortcut('Ctrl+S')
        save_with_control_file_action.triggered.connect(self.output_tptp_syntax_from_control_file_without_comments)

        save_tptp_grammar_file_from_selection_action = QAction('&Reduce and save TPTP syntax with selection', self)
        save_tptp_grammar_file_from_selection_action.setShortcut('Ctrl+D')
        save_tptp_grammar_file_from_selection_action.triggered.connect(self.create_tptp_syntax_file_from_selection_without_comments)

        produce_reduced_tptp_grammar_action = QAction('&Reduce TPTP syntax with selection', self)
        produce_reduced_tptp_grammar_action.setShortcut('Ctrl+R')
        produce_reduced_tptp_grammar_action.triggered.connect(self.reduce_tptp_syntax_with_selection)

        save_control_file_action = QAction('&Produce and save control file from selection', self)
        save_control_file_action.setShortcut('Ctrl+F')
        save_control_file_action.triggered.connect(self.output_control_file)

        toggle_comments_action = QAction('&Toggle comments', self)
        toggle_comments_action.setShortcut('Ctrl+C')
        toggle_comments_action.triggered.connect(self.toggle_comments)

        import_control_file_action = QAction('&Import control file', self)
        import_control_file_action.setShortcut('Ctrl+O')
        import_control_file_action.triggered.connect(self.load_control_file)

        save_with_control_file_comments_action = QAction('&Reduce and save TPTP syntax with control file with external comment syntax', self)
        save_with_control_file_comments_action.triggered.connect(self.create_tptp_syntax_from_control_file_with_comments)

        save_tptp_grammar_file_from_selection_comments_action = QAction('&Reduce and save TPTP syntax from selection with external comment syntax', self)
        save_tptp_grammar_file_from_selection_comments_action.triggered.connect(self.create_tptp_syntax_file_from_selection_with_comments)

        menubar = QMenuBar()
        self.setMenuBar(menubar)
        menubar.setNativeMenuBar(False)

        import_menu = menubar.addMenu("Import syntax")
        import_menu.addAction(import_tptp_file_action)
        import_menu.addAction(import_tptp_file_from_web_action)

        save_menu = menubar.addMenu("Save syntax")
        save_menu.addAction(save_tptp_grammar_file_from_selection_action)
        save_menu.addAction(save_with_control_file_action)
        save_menu.addSeparator()
        save_menu.addAction(save_with_control_file_comments_action)
        save_menu.addAction(save_tptp_grammar_file_from_selection_comments_action)

        reduce_menu = menubar.addMenu("Reduce")
        reduce_menu.addAction(produce_reduced_tptp_grammar_action)

        control_file_menu = menubar.addMenu("Control file")
        control_file_menu.addAction(import_control_file_action)
        control_file_menu.addAction(save_control_file_action)

        view_menu = menubar.addMenu("View")
        view_menu.addAction(toggle_comments_action)

        self.setWindowTitle('TPTP sub-syntax extractor')
        self.showMaximized()
Esempio n. 11
0
    def ui(self):
        menubar = QMenuBar()
        menubar.setNativeMenuBar(True)  # make the menu bar OS specific

        bar_file = menubar.addMenu(self.tr("&File"))

        file_load = QAction(self.tr("&Load image"), self,
                            shortcut=QKeySequence.New,
                            statusTip=self.tr("Load a new image"),
                            triggered=self.open_file)

        file_save = QAction(self.tr("&Save plate"), self,
                            shortcut=QKeySequence.Save,
                            statusTip=self.tr("Save the pattern"),
                            triggered=self.save_file)

        file_print = QAction(self.tr("&Print"), self,
                             shortcut=QKeySequence.Print,
                             statusTip=self.tr("Print pixel pattern"),
                             triggered=self.print_file)

        file_settings = QAction(self.tr("S&ettings"), self,
                                statusTip=self.tr('Change settings'),
                                triggered=self.change_settings)

        file_quit = QAction(self.tr("&Quit"), self, shortcut=QKeySequence.Quit,
                            statusTip=self.tr('Quit the program'),
                            triggered=self.close)

        bar_file.addAction(file_load)
        bar_file.addAction(file_save)
        bar_file.addAction(file_print)
        bar_file.addAction(file_settings)
        bar_file.addAction(file_quit)

        bar_about = menubar.addMenu(self.tr("&About"))
        about_about = QAction(self.tr("&About"), self,
                              statusTip=self.tr("Show about PyBigPix"),
                              triggered=self.show_about)

        about_licence = QAction(self.tr("&License"), self,
                                statusTip=self.tr('Show license'),
                                triggered=self.show_license)

        about_QT = QAction(self.tr("About &QT"), self,
                           statusTip=self.tr("Show about QT"),
                           triggered=qApp.aboutQt)

        bar_about.addAction(about_about)
        bar_about.addAction(about_licence)
        bar_about.addAction(about_QT)

        self.setMenuWidget(menubar)
        self.setMenuBar(menubar)

        self.setWindowTitle(self.window_title)

        self.label_image = QLabel(self.tr("Start Image"))
        self.label_image.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        self.label_image.setMinimumSize(400, 400)
        self.label_image.textFormat()
        self.label_image.setFrameShape(QFrame.Panel)
        self.label_image.setAlignment(Qt.AlignCenter)

        self.lable_pixels = QLabel(self.tr("Pixel Image"))
        self.lable_pixels.setMinimumSize(400, 400)
        self.lable_pixels.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        self.lable_pixels.setAlignment(Qt.AlignCenter)
        self.lable_pixels.setFrameShape(QFrame.Panel)

        self.centeralwidget = QWidget()
        layout = QHBoxLayout(self.centeralwidget)
        layout.addWidget(self.label_image)
        layout.addWidget(self.lable_pixels)
        self.setCentralWidget(self.centeralwidget)
Esempio n. 12
0
    def _build_ui(self):
        layout = QGridLayout()

        tabs = QTabWidget()
        calc_widget = QWidget()
        calc_layout = QFormLayout(calc_widget)
        vis_widget = QWidget()
        vis_layout = QFormLayout(vis_widget)
        layout.addWidget(tabs)

        tabs.addTab(calc_widget, "calculation")
        tabs.addTab(vis_widget, "visualization")

        self.radii_option = QComboBox()
        self.radii_option.addItems(["Bondi", "UMN"])
        ndx = self.radii_option.findText(self.settings.radii, Qt.MatchExactly)
        self.radii_option.setCurrentIndex(ndx)
        calc_layout.addRow("radii:", self.radii_option)

        self.scale = QDoubleSpinBox()
        self.scale.setValue(self.settings.vdw_scale)
        self.scale.setSingleStep(0.01)
        self.scale.setRange(1., 1.5)
        calc_layout.addRow("VDW scale:", self.scale)

        set_ligand_atoms = QPushButton("set ligands to current selection")
        set_ligand_atoms.clicked.connect(self.set_ligand_atoms)
        set_ligand_atoms.setToolTip(
            "specify atoms to use in calculation\n" +
            "by default, all atoms will be used unless a single center is specified\n"
            +
            "in the case of a single center, all atoms except the center is used"
        )
        calc_layout.addRow(set_ligand_atoms)
        self.set_ligand_atoms = set_ligand_atoms

        self.radius = QDoubleSpinBox()
        self.radius.setValue(self.settings.center_radius)
        self.radius.setSuffix(" \u212B")
        self.radius.setDecimals(1)
        self.radius.setSingleStep(0.1)
        self.radius.setRange(1., 15.)
        calc_layout.addRow("radius around center:", self.radius)

        self.method = QComboBox()
        self.method.addItems(["Lebedev", "Monte-Carlo"])
        self.method.setToolTip("Lebedev: deterministic method\n" +
                               "Monte-Carlo: non-deterministic method")
        ndx = self.method.findText(self.settings.method, Qt.MatchExactly)
        self.method.setCurrentIndex(ndx)
        calc_layout.addRow("integration method:", self.method)

        leb_widget = QWidget()
        leb_layout = QFormLayout(leb_widget)
        leb_layout.setContentsMargins(0, 0, 0, 0)

        self.radial_points = QComboBox()
        self.radial_points.addItems(["20", "32", "64", "75", "99", "127"])
        self.radial_points.setToolTip(
            "more radial points will give more accurate results, but integration will take longer"
        )
        ndx = self.radial_points.findText(self.settings.radial_points,
                                          Qt.MatchExactly)
        self.radial_points.setCurrentIndex(ndx)
        leb_layout.addRow("radial points:", self.radial_points)

        self.angular_points = QComboBox()
        self.angular_points.addItems([
            "110", "194", "302", "590", "974", "1454", "2030", "2702", "5810"
        ])
        self.angular_points.setToolTip(
            "more angular points will give more accurate results, but integration will take longer"
        )
        ndx = self.angular_points.findText(self.settings.angular_points,
                                           Qt.MatchExactly)
        self.angular_points.setCurrentIndex(ndx)
        leb_layout.addRow("angular points:", self.angular_points)

        calc_layout.addRow(leb_widget)

        mc_widget = QWidget()
        mc_layout = QFormLayout(mc_widget)
        mc_layout.setContentsMargins(0, 0, 0, 0)

        self.min_iter = QSpinBox()
        self.min_iter.setValue(self.settings.minimum_iterations)
        self.min_iter.setRange(0, 10000)
        self.min_iter.setToolTip(
            "each iteration is 3000 points\n" +
            "iterations continue until convergence criteria are met")
        mc_layout.addRow("minimum interations:", self.min_iter)

        calc_layout.addRow(mc_widget)

        if self.settings.method == "Lebedev":
            mc_widget.setVisible(False)
        elif self.settings.method == "Monte-Carlo":
            leb_widget.setVisible(False)

        self.method.currentTextChanged.connect(
            lambda text, widget=leb_widget: widget.setVisible(text == "Lebedev"
                                                              ))
        self.method.currentTextChanged.connect(
            lambda text, widget=mc_widget: widget.setVisible(text ==
                                                             "Monte-Carlo"))

        self.use_centroid = QCheckBox()
        self.use_centroid.setChecked(self.settings.use_centroid)
        self.use_centroid.setToolTip(
            "place the center between selected atoms\n" +
            "might be useful for polydentate ligands")
        calc_layout.addRow("use centroid of centers:", self.use_centroid)

        steric_map_options = QGroupBox("steric map")
        steric_map_layout = QFormLayout(steric_map_options)

        self.steric_map = QCheckBox()
        self.steric_map.setChecked(self.settings.steric_map)
        self.steric_map.setToolTip(
            "produce a 2D projection of steric bulk\ncauses buried volume to be reported for individual quadrants"
        )
        steric_map_layout.addRow("create steric map:", self.steric_map)

        self.use_scene = QCheckBox()
        self.use_scene.setChecked(self.settings.use_scene)
        self.use_scene.setToolTip(
            "steric map will use the orientation the molecule is displayed in")
        steric_map_layout.addRow("use display orientation:", self.use_scene)

        self.num_pts = QSpinBox()
        self.num_pts.setRange(25, 250)
        self.num_pts.setValue(self.settings.num_pts)
        self.num_pts.setToolTip("number of points along x and y axes")
        steric_map_layout.addRow("number of points:", self.num_pts)

        self.include_vbur = QCheckBox()
        self.include_vbur.setChecked(self.settings.include_vbur)
        steric_map_layout.addRow("label quadrants with %V<sub>bur</sub>",
                                 self.include_vbur)

        self.map_shape = QComboBox()
        self.map_shape.addItems(["circle", "square"])
        ndx = self.map_shape.findText(self.settings.map_shape, Qt.MatchExactly)
        self.map_shape.setCurrentIndex(ndx)
        steric_map_layout.addRow("map shape:", self.map_shape)

        self.auto_minmax = QCheckBox()
        self.auto_minmax.setChecked(self.settings.auto_minmax)
        steric_map_layout.addRow("automatic min. and max.:", self.auto_minmax)

        self.map_min = QDoubleSpinBox()
        self.map_min.setRange(-15., 0.)
        self.map_min.setSuffix(" \u212B")
        self.map_min.setSingleStep(0.1)
        self.map_min.setValue(self.settings.map_min)
        steric_map_layout.addRow("minimum value:", self.map_min)

        self.map_max = QDoubleSpinBox()
        self.map_max.setRange(0., 15.)
        self.map_max.setSuffix(" \u212B")
        self.map_max.setSingleStep(0.1)
        self.map_max.setValue(self.settings.map_max)
        steric_map_layout.addRow("maximum value:", self.map_max)

        self.use_scene.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.use_scene: widget.setEnabled(state == Qt.
                                                                   Checked))

        self.num_pts.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.num_pts: widget.setEnabled(state == Qt.
                                                                 Checked))

        self.include_vbur.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.include_vbur: widget.setEnabled(
                state == Qt.Checked))

        self.map_shape.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.map_shape: widget.setEnabled(state == Qt.
                                                                   Checked))

        self.auto_minmax.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.auto_minmax: widget.setEnabled(
                state == Qt.Checked))

        self.map_min.setEnabled(not self.settings.auto_minmax
                                and self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.map_min, widget2=self.auto_minmax: widget
            .setEnabled(state == Qt.Checked and not widget2.isChecked()))
        self.auto_minmax.stateChanged.connect(
            lambda state, widget=self.map_min, widget2=self.steric_map: widget.
            setEnabled(not state == Qt.Checked and widget2.isChecked()))

        self.map_max.setEnabled(not self.settings.auto_minmax
                                and self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.map_max, widget2=self.auto_minmax: widget
            .setEnabled(state == Qt.Checked and not widget2.isChecked()))
        self.auto_minmax.stateChanged.connect(
            lambda state, widget=self.map_max, widget2=self.steric_map: widget.
            setEnabled(not state == Qt.Checked and widget2.isChecked()))

        vis_layout.addRow(steric_map_options)

        cutout_options = QGroupBox("volume cutout")
        cutout_layout = QFormLayout(cutout_options)

        self.display_cutout = QComboBox()
        self.display_cutout.addItems(["no", "free", "buried"])
        ndx = self.display_cutout.findText(self.settings.display_cutout,
                                           Qt.MatchExactly)
        self.display_cutout.setCurrentIndex(ndx)
        self.display_cutout.setToolTip("show free or buried volume")
        cutout_layout.addRow("display volume:", self.display_cutout)

        self.point_spacing = QDoubleSpinBox()
        self.point_spacing.setDecimals(3)
        self.point_spacing.setRange(0.01, 0.5)
        self.point_spacing.setSingleStep(0.005)
        self.point_spacing.setSuffix(" \u212B")
        self.point_spacing.setValue(self.settings.point_spacing)
        self.point_spacing.setToolTip(
            "distance between points on cutout\n" +
            "smaller spacing will narrow gaps, but increase time to create the cutout"
        )
        cutout_layout.addRow("point spacing:", self.point_spacing)

        self.intersection_scale = QDoubleSpinBox()
        self.intersection_scale.setDecimals(2)
        self.intersection_scale.setRange(1., 10.)
        self.intersection_scale.setSingleStep(0.5)
        self.intersection_scale.setSuffix("x")
        self.intersection_scale.setToolTip(
            "relative density of points where VDW radii intersect\n" +
            "higher density will narrow gaps, but increase time to create cutout"
        )
        self.intersection_scale.setValue(self.settings.intersection_scale)
        cutout_layout.addRow("intersection density:", self.intersection_scale)

        self.point_spacing.setEnabled(self.settings.display_cutout != "no")
        self.intersection_scale.setEnabled(
            self.settings.display_cutout != "no")

        self.display_cutout.currentTextChanged.connect(
            lambda text, widget=self.point_spacing: widget.setEnabled(text !=
                                                                      "no"))
        self.display_cutout.currentTextChanged.connect(
            lambda text, widget=self.intersection_scale: widget.setEnabled(
                text != "no"))

        vis_layout.addRow(cutout_options)

        calc_vbur_button = QPushButton(
            "calculate % buried volume for selected centers")
        calc_vbur_button.clicked.connect(self.calc_vbur)
        calc_layout.addRow(calc_vbur_button)
        self.calc_vbur_button = calc_vbur_button

        remove_vbur_button = QPushButton(
            "remove % buried volume visualizations")
        remove_vbur_button.clicked.connect(self.del_vbur)
        cutout_layout.addRow(remove_vbur_button)

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(['model', 'center', '%Vbur'])
        self.table.setSelectionBehavior(QTableWidget.SelectRows)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.resizeColumnToContents(0)
        self.table.resizeColumnToContents(1)
        self.table.resizeColumnToContents(2)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.Stretch)
        calc_layout.addRow(self.table)

        menu = QMenuBar()

        export = menu.addMenu("&Export")
        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)
        self.copy = copy

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        comma.setChecked(self.settings.delimiter == "comma")
        comma.triggered.connect(lambda *args, delim="comma": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        space = QAction("space", self.tool_window.ui_area, checkable=True)
        space.setChecked(self.settings.delimiter == "space")
        space.triggered.connect(lambda *args, delim="space": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        comma.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        tab.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        space.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        semicolon.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=space: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Esempio n. 13
0
    def _build_ui(self):
        #each group has an empty widget at the bottom so they resize the way I want while also having the
        #labels where I want them
        layout = QGridLayout()

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

        #layout for absolute thermo stuff
        absolute_widget = QWidget()
        absolute_layout = QGridLayout(absolute_widget)

        #box for sp
        sp_area_widget = QGroupBox("Single-point")
        sp_layout = QGridLayout(sp_area_widget)

        self.sp_selector = FilereaderComboBox(self.session,
                                              otherItems=['energy'])
        self.sp_selector.currentIndexChanged.connect(self.set_sp)
        sp_layout.addWidget(self.sp_selector, 0, 0, 1, 3, Qt.AlignTop)

        nrg_label = QLabel("E =")
        sp_layout.addWidget(nrg_label, 1, 0, 1, 1,
                            Qt.AlignRight | Qt.AlignVCenter)

        self.sp_nrg_line = QLineEdit()
        self.sp_nrg_line.setReadOnly(True)
        self.sp_nrg_line.setToolTip("electronic energy")
        sp_layout.addWidget(self.sp_nrg_line, 1, 1, 1, 1, Qt.AlignTop)

        sp_layout.addWidget(QLabel("E<sub>h</sub>"), 1, 2, 1, 1,
                            Qt.AlignVCenter)

        sp_layout.addWidget(QWidget(), 2, 0)

        sp_layout.setColumnStretch(0, 0)
        sp_layout.setColumnStretch(1, 1)
        sp_layout.setRowStretch(0, 0)
        sp_layout.setRowStretch(1, 0)
        sp_layout.setRowStretch(2, 1)

        row = 0
        #box for thermo
        therm_area_widget = QGroupBox("Thermal corrections")
        thermo_layout = QGridLayout(therm_area_widget)

        self.thermo_selector = FilereaderComboBox(self.session,
                                                  otherItems=['frequency'])
        self.thermo_selector.currentIndexChanged.connect(self.set_thermo_mdl)
        thermo_layout.addWidget(self.thermo_selector, row, 0, 1, 3,
                                Qt.AlignTop)

        row += 1

        thermo_layout.addWidget(QLabel("T ="), row, 0, 1, 1,
                                Qt.AlignRight | Qt.AlignVCenter)

        self.temperature_line = QDoubleSpinBox()
        self.temperature_line.setMaximum(2**31 - 1)
        self.temperature_line.setValue(298.15)
        self.temperature_line.setSingleStep(10)
        self.temperature_line.setSuffix(" K")
        self.temperature_line.setMinimum(0)
        self.temperature_line.valueChanged.connect(self.set_thermo)
        thermo_layout.addWidget(self.temperature_line, row, 1, 1, 2,
                                Qt.AlignTop)

        row += 1

        thermo_layout.addWidget(QLabel("𝜔<sub>0</sub> ="), row, 0, 1, 1,
                                Qt.AlignRight | Qt.AlignVCenter)

        self.v0_edit = QDoubleSpinBox()
        self.v0_edit.setMaximum(4000)
        self.v0_edit.setValue(self.settings.w0)
        self.v0_edit.setSingleStep(25)
        self.v0_edit.setSuffix(" cm\u207b\u00b9")
        self.v0_edit.valueChanged.connect(self.set_thermo)
        self.v0_edit.setMinimum(0)
        self.v0_edit.setToolTip(
            "frequency parameter for quasi treatments of entropy")
        thermo_layout.addWidget(self.v0_edit, row, 1, 1, 2, Qt.AlignTop)

        row += 1

        thermo_layout.addWidget(QLabel("𝛿ZPE ="), row, 0, 1, 1,
                                Qt.AlignRight | Qt.AlignVCenter)

        self.zpe_line = QLineEdit()
        self.zpe_line.setReadOnly(True)
        self.zpe_line.setToolTip("zero-point energy correction")
        thermo_layout.addWidget(self.zpe_line, row, 1, 1, 1, Qt.AlignTop)

        thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                                Qt.AlignVCenter)

        row += 1

        thermo_layout.addWidget(QLabel("𝛿H<sub>RRHO</sub> ="), row, 0, 1, 1,
                                Qt.AlignRight | Qt.AlignVCenter)

        self.enthalpy_line = QLineEdit()
        self.enthalpy_line.setReadOnly(True)
        self.enthalpy_line.setToolTip("RRHO enthalpy correction")
        thermo_layout.addWidget(self.enthalpy_line, row, 1, 1, 1, Qt.AlignTop)

        thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                                Qt.AlignVCenter)

        row += 1

        thermo_layout.addWidget(QLabel("𝛿G<sub>RRHO</sub> ="), row, 0, 1, 1,
                                Qt.AlignRight | Qt.AlignVCenter)

        self.rrho_g_line = QLineEdit()
        self.rrho_g_line.setReadOnly(True)
        self.rrho_g_line.setToolTip(
            """RRHO free energy correction\nRotational motion is completely independent from vibrations\nNormal mode vibrations behave like harmonic oscillators"""
        )
        thermo_layout.addWidget(self.rrho_g_line, row, 1, 1, 1, Qt.AlignTop)

        thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                                Qt.AlignVCenter)

        row += 1

        dqrrho_g_label = QLabel()
        dqrrho_g_label.setText(
            "<a href=\"Grimme's Quasi-RRHO\" style=\"text-decoration: none;\">𝛿G<sub>Quasi-RRHO</sub></a> ="
        )
        dqrrho_g_label.setTextFormat(Qt.RichText)
        dqrrho_g_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        dqrrho_g_label.linkActivated.connect(self.open_link)
        dqrrho_g_label.setToolTip("click to open a relevant reference\n" + \
                                  "see the \"Computation of internal (gas‐phase) entropies\" section for a description of the method")

        thermo_layout.addWidget(dqrrho_g_label, row, 0, 1, 1,
                                Qt.AlignRight | Qt.AlignVCenter)

        self.qrrho_g_line = QLineEdit()
        self.qrrho_g_line.setReadOnly(True)
        self.qrrho_g_line.setToolTip("Quasi-RRHO free energy correction\n" + \
        "Vibrational entropy of each mode is weighted and complemented with rotational entropy\n" + \
        "The weighting is much lower for modes with frequencies less than 𝜔\u2080")
        thermo_layout.addWidget(self.qrrho_g_line, row, 1, 1, 1, Qt.AlignTop)

        thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                                Qt.AlignVCenter)

        row += 1

        dqharm_g_label = QLabel("")
        dqharm_g_label.setText(
            "<a href=\"Truhlar's Quasi-Harmonic\" style=\"text-decoration: none;\">𝛿G<sub>Quasi-Harmonic</sub></a> ="
        )
        dqharm_g_label.setTextFormat(Qt.RichText)
        dqharm_g_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        dqharm_g_label.linkActivated.connect(self.open_link)
        dqharm_g_label.setToolTip("click to open a relevant reference\n" + \
                                  "see the \"Computations\" section for a description of the method")

        thermo_layout.addWidget(dqharm_g_label, row, 0, 1, 1,
                                Qt.AlignRight | Qt.AlignVCenter)

        self.qharm_g_line = QLineEdit()
        self.qharm_g_line.setReadOnly(True)
        self.qharm_g_line.setToolTip("Quasi-hamonic free energy correction\n" + \
        "For entropy, real vibrational modes lower than 𝜔\u2080 are treated as 𝜔\u2080")
        thermo_layout.addWidget(self.qharm_g_line, row, 1, 1, 1, Qt.AlignTop)

        thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                                Qt.AlignVCenter)

        thermo_layout.addWidget(QWidget(), row + 1, 0)

        thermo_layout.setColumnStretch(0, 0)
        thermo_layout.setColumnStretch(1, 1)
        for i in range(0, row):
            thermo_layout.setRowStretch(i, 0)

        thermo_layout.setRowStretch(row + 1, 1)

        row = 0
        # for for total
        sum_area_widget = QGroupBox("Thermochemistry")
        sum_layout = QGridLayout(sum_area_widget)

        sum_layout.addWidget(QLabel("ZPE ="), row, 0, 1, 1,
                             Qt.AlignRight | Qt.AlignVCenter)

        self.zpe_sum_line = QLineEdit()
        self.zpe_sum_line.setReadOnly(True)
        self.zpe_sum_line.setToolTip(
            "sum of electronic energy and ZPE correction")
        sum_layout.addWidget(self.zpe_sum_line, row, 1, 1, 1, Qt.AlignTop)

        sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                             Qt.AlignVCenter)

        row += 1

        sum_layout.addWidget(QLabel("H<sub>RRHO</sub> ="), row, 0, 1, 1,
                             Qt.AlignRight | Qt.AlignVCenter)

        self.h_sum_line = QLineEdit()
        self.h_sum_line.setReadOnly(True)
        self.h_sum_line.setToolTip(
            "sum of electronic energy and RRHO enthalpy correction")
        sum_layout.addWidget(self.h_sum_line, row, 1, 1, 1, Qt.AlignTop)

        sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                             Qt.AlignVCenter)

        row += 1

        sum_layout.addWidget(QLabel("G<sub>RRHO</sub> ="), row, 0, 1, 1,
                             Qt.AlignRight | Qt.AlignVCenter)

        self.rrho_g_sum_line = QLineEdit()
        self.rrho_g_sum_line.setReadOnly(True)
        self.rrho_g_sum_line.setToolTip(
            "sum of electronic energy and RRHO free energy correction\nRotational motion is completely independent from vibrations\nNormal mode vibrations behave like harmonic oscillators"
        )
        sum_layout.addWidget(self.rrho_g_sum_line, row, 1, 1, 1, Qt.AlignTop)

        sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                             Qt.AlignVCenter)

        row += 1

        sum_layout.addWidget(QLabel("G<sub>Quasi-RRHO</sub> ="), row, 0, 1, 1,
                             Qt.AlignRight | Qt.AlignVCenter)

        self.qrrho_g_sum_line = QLineEdit()
        self.qrrho_g_sum_line.setReadOnly(True)
        self.qrrho_g_sum_line.setToolTip("Sum of electronic energy and quasi-RRHO free energy correction\n" + \
        "Vibrational entropy of each mode is weighted and complemented with rotational entropy\n" + \
        "The weighting is much lower for modes with frequencies less than 𝜔\u2080")
        sum_layout.addWidget(self.qrrho_g_sum_line, row, 1, 1, 1, Qt.AlignTop)

        sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                             Qt.AlignVCenter)

        row += 1

        sum_layout.addWidget(QLabel("G<sub>Quasi-Harmonic</sub> ="), row, 0, 1,
                             1, Qt.AlignRight | Qt.AlignVCenter)

        self.qharm_g_sum_line = QLineEdit()
        self.qharm_g_sum_line.setReadOnly(True)
        self.qharm_g_sum_line.setToolTip("Sum of electronic energy and quasi-harmonic free energy correction\n" + \
        "For entropy, real vibrational modes lower than 𝜔\u2080 are treated as 𝜔\u2080")
        sum_layout.addWidget(self.qharm_g_sum_line, row, 1, 1, 1, Qt.AlignTop)

        sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1,
                             Qt.AlignVCenter)

        sum_layout.addWidget(QWidget(), row + 1, 0)

        sum_layout.setColumnStretch(0, 0)
        for i in range(0, row):
            sum_layout.setRowStretch(i, 0)

        sum_layout.setRowStretch(row + 1, 1)

        splitter = QSplitter(Qt.Horizontal)
        splitter.setChildrenCollapsible(False)
        splitter.addWidget(sp_area_widget)
        splitter.addWidget(therm_area_widget)
        splitter.addWidget(sum_area_widget)

        absolute_layout.addWidget(splitter)

        self.status = QStatusBar()
        self.status.setSizeGripEnabled(False)
        self.status.setStyleSheet("color: red")
        absolute_layout.addWidget(self.status, 1, 0, 1, 1, Qt.AlignTop)

        self.tab_widget.addTab(absolute_widget, "absolute")

        relative_widget = QWidget()
        relative_layout = QGridLayout(relative_widget)

        size = [self.settings.ref_col_1, self.settings.ref_col_2]
        self.ref_group = ThermoGroup("reference group", self.session,
                                     self.nrg_fr, self.thermo_co, size)
        self.ref_group.changes.connect(self.calc_relative_thermo)
        relative_layout.addWidget(self.ref_group, 0, 0, 1, 3, Qt.AlignTop)

        size = [self.settings.other_col_1, self.settings.other_col_2]
        self.other_group = ThermoGroup("other group", self.session,
                                       self.nrg_fr, self.thermo_co, size)
        self.other_group.changes.connect(self.calc_relative_thermo)
        relative_layout.addWidget(self.other_group, 0, 3, 1, 3, Qt.AlignTop)

        self.relative_temperature = QDoubleSpinBox()
        self.relative_temperature.setMaximum(2**31 - 1)
        self.relative_temperature.setValue(self.settings.rel_temp)
        self.relative_temperature.setSingleStep(10)
        self.relative_temperature.setSuffix(" K")
        self.relative_temperature.setMinimum(0)
        self.relative_temperature.valueChanged.connect(
            self.calc_relative_thermo)
        relative_layout.addWidget(QLabel("T ="), 1, 0, 1, 1,
                                  Qt.AlignRight | Qt.AlignVCenter)
        relative_layout.addWidget(self.relative_temperature, 1, 1, 1, 5,
                                  Qt.AlignLeft | Qt.AlignVCenter)

        self.relative_v0 = QDoubleSpinBox()
        self.relative_v0.setMaximum(2**31 - 1)
        self.relative_v0.setValue(self.settings.w0)
        self.relative_v0.setSingleStep(25)
        self.relative_v0.setSuffix(" cm\u207b\u00b9")
        self.relative_v0.setMinimum(0)
        self.relative_v0.setToolTip(
            "frequency parameter for quasi treatments of entropy")
        self.relative_v0.valueChanged.connect(self.calc_relative_thermo)
        relative_layout.addWidget(QLabel("𝜔<sub>0</sub> ="), 2, 0, 1, 1,
                                  Qt.AlignRight | Qt.AlignVCenter)
        relative_layout.addWidget(self.relative_v0, 2, 1, 1, 5,
                                  Qt.AlignLeft | Qt.AlignVCenter)

        relative_layout.addWidget(
            QLabel("Boltzmann-weighted relative energies in kcal/mol:"), 3, 0,
            1, 6, Qt.AlignVCenter | Qt.AlignLeft)

        relative_layout.addWidget(QLabel("ΔE"), 4, 0,
                                  Qt.AlignTop | Qt.AlignVCenter)
        self.relative_dE = QLineEdit()
        self.relative_dE.setReadOnly(True)
        relative_layout.addWidget(self.relative_dE, 5, 0,
                                  Qt.AlignTop | Qt.AlignVCenter)

        relative_layout.addWidget(QLabel("ΔZPE"), 4, 1,
                                  Qt.AlignTop | Qt.AlignVCenter)
        self.relative_dZPVE = QLineEdit()
        self.relative_dZPVE.setReadOnly(True)
        relative_layout.addWidget(self.relative_dZPVE, 5, 1,
                                  Qt.AlignTop | Qt.AlignVCenter)

        relative_layout.addWidget(QLabel("ΔH<sub>RRHO</sub>"), 4, 2,
                                  Qt.AlignTop | Qt.AlignVCenter)
        self.relative_dH = QLineEdit()
        self.relative_dH.setReadOnly(True)
        relative_layout.addWidget(self.relative_dH, 5, 2,
                                  Qt.AlignTop | Qt.AlignVCenter)

        relative_layout.addWidget(QLabel("ΔG<sub>RRHO</sub>"), 4, 3,
                                  Qt.AlignTop | Qt.AlignVCenter)
        self.relative_dG = QLineEdit()
        self.relative_dG.setReadOnly(True)
        relative_layout.addWidget(self.relative_dG, 5, 3,
                                  Qt.AlignTop | Qt.AlignVCenter)

        relative_layout.addWidget(QLabel("ΔG<sub>Quasi-RRHO</sub>"), 4, 4,
                                  Qt.AlignTop | Qt.AlignVCenter)
        self.relative_dQRRHOG = QLineEdit()
        self.relative_dQRRHOG.setReadOnly(True)
        relative_layout.addWidget(self.relative_dQRRHOG, 5, 4,
                                  Qt.AlignTop | Qt.AlignVCenter)

        relative_layout.addWidget(QLabel("ΔG<sub>Quasi-Harmonic</sub>"), 4, 5,
                                  Qt.AlignTop | Qt.AlignVCenter)
        self.relative_dQHARMG = QLineEdit()
        self.relative_dQHARMG.setReadOnly(True)
        relative_layout.addWidget(self.relative_dQHARMG, 5, 5,
                                  Qt.AlignTop | Qt.AlignVCenter)

        relative_layout.setRowStretch(0, 1)
        relative_layout.setRowStretch(1, 0)
        relative_layout.setRowStretch(2, 0)
        relative_layout.setRowStretch(3, 0)
        relative_layout.setRowStretch(4, 0)
        relative_layout.setRowStretch(5, 0)

        self.tab_widget.addTab(relative_widget, "relative")

        #menu stuff
        menu = QMenuBar()

        export = menu.addMenu("&Export")
        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)
        self.copy = copy

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        comma.setChecked(self.settings.delimiter == "comma")
        comma.triggered.connect(lambda *args, delim="comma": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        space = QAction("space", self.tool_window.ui_area, checkable=True)
        space.setChecked(self.settings.delimiter == "space")
        space.triggered.connect(lambda *args, delim="space": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        comma.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        tab.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        space.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        semicolon.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=space: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Esempio n. 14
0
    def _build_ui(self):
        layout = QFormLayout()

        self.radii_option = QComboBox()
        self.radii_option.addItems(["Bondi", "UMN"])
        ndx = self.radii_option.findText(self.settings.radii, Qt.MatchExactly)
        self.radii_option.setCurrentIndex(ndx)
        layout.addRow("radii:", self.radii_option)

        self.display_vectors = QCheckBox()
        self.display_vectors.setChecked(self.settings.display_vectors)
        layout.addRow("show vectors:", self.display_vectors)

        self.display_radii = QCheckBox()
        self.display_radii.setChecked(self.settings.display_radii)
        layout.addRow("show radii:", self.display_radii)

        calc_sterimol_button = QPushButton(
            "calculate parameters for selected substituents")
        calc_sterimol_button.clicked.connect(self.calc_sterimol)
        layout.addRow(calc_sterimol_button)
        self.calc_sterimol_button = calc_sterimol_button

        remove_sterimol_button = QPushButton("remove Sterimol visualizations")
        remove_sterimol_button.clicked.connect(self.del_sterimol)
        layout.addRow(remove_sterimol_button)
        self.remove_sterimol_button = remove_sterimol_button

        self.table = QTableWidget()
        self.table.setColumnCount(8)
        self.table.setHorizontalHeaderLabels([
            'substituent atom',
            'bonded atom',
            'B\u2081',
            'B\u2082',
            'B\u2083',
            'B\u2084',
            'B\u2085',
            'L',
        ])
        self.table.setSelectionBehavior(QTableWidget.SelectRows)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.resizeColumnToContents(0)
        self.table.resizeColumnToContents(1)
        self.table.resizeColumnToContents(2)
        self.table.resizeColumnToContents(3)
        self.table.resizeColumnToContents(4)
        self.table.resizeColumnToContents(5)
        self.table.resizeColumnToContents(6)
        self.table.resizeColumnToContents(7)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            3, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            4, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            5, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            6, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            7, QHeaderView.Stretch)
        layout.addRow(self.table)

        menu = QMenuBar()

        export = menu.addMenu("&Export")
        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        comma.setChecked(self.settings.delimiter == "comma")
        comma.triggered.connect(lambda *args, delim="comma": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        space = QAction("space", self.tool_window.ui_area, checkable=True)
        space.setChecked(self.settings.delimiter == "space")
        space.triggered.connect(lambda *args, delim="space": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        comma.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        tab.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        space.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        semicolon.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=space: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Esempio n. 15
0
    def _build_ui(self):
        layout = QGridLayout()

        self.figure = Figure(figsize=(2, 2))
        self.canvas = Canvas(self.figure)

        ax = self.figure.add_axes((0.15, 0.20, 0.80, 0.70))

        fr = self.filereader
        if fr.all_geom is None:
            self.opened = False
            return

        data = []
        for step in fr.all_geom:
            info = [
                item for item in step
                if isinstance(item, dict) and "energy" in item
            ]
            if len(info) < 1:
                #we will be unable to load an enegy plot because some structure does not have an associated energy
                self.opened = False
                self.session.logger.error(
                    "not enough iterations to plot - %i found" % len(info))
                return
            else:
                info = info[0]
            data.append(info["energy"])

        self.ys = data

        se = np.ptp(data)

        self.nrg_plot = ax.plot(self.structure.coordset_ids,
                                data,
                                marker='o',
                                c='gray',
                                markersize=3)
        self.nrg_plot = self.nrg_plot[0]
        ax.set_xlabel('iteration')
        ax.set_ylabel(r'energy ($E_h$)')
        ax.set_ylim(bottom=(min(data) - se / 10), top=(max(data) + se / 10))

        minlocs = [
            self.structure.coordset_ids[i]
            for i in range(0, self.structure.num_coordsets)
            if data[i] == min(data)
        ]
        mins = [min(data) for m in minlocs]

        maxlocs = [
            self.structure.coordset_ids[i]
            for i in range(0, self.structure.num_coordsets)
            if data[i] == max(data)
        ]
        maxs = [max(data) for m in minlocs]

        ax.plot(minlocs, mins, marker='*', c='blue', markersize=5)
        ax.plot(maxlocs, maxs, marker='*', c='red', markersize=5)

        ax.ticklabel_format(axis='y',
                            style='sci',
                            scilimits=(0, 0),
                            useOffset=True)
        ax.ticklabel_format(axis='x', style='plain', useOffset=False)

        self.canvas.mpl_connect('button_release_event', self.unclick)
        self.canvas.mpl_connect('button_press_event', self.onclick)
        self.canvas.mpl_connect('motion_notify_event', self.drag)
        self.canvas.mpl_connect('scroll_event', self.zoom)

        self.annotation = ax.annotate("",
                                      xy=(0, 0),
                                      xytext=(0, 10),
                                      textcoords="offset points",
                                      fontfamily='Arial')
        self.annotation.set_visible(False)

        ax.autoscale()
        self.canvas.draw()
        self.canvas.setMinimumWidth(400)
        self.canvas.setMinimumHeight(200)
        layout.addWidget(self.canvas)

        toolbar_widget = QWidget()
        toolbar = NavigationToolbar(self.canvas, toolbar_widget)

        toolbar.setMaximumHeight(32)
        self.toolbar = toolbar
        layout.addWidget(toolbar)

        #menu bar for saving stuff
        menu = QMenuBar()
        file = menu.addMenu("&Export")
        file.addAction("&Save CSV...")

        file.triggered.connect(self.save)

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)

        self.opened = True
Esempio n. 16
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # Proyecto
        self.project = None

        # Título
        self.setWindowTitle("3D Cell Reconstruction")

        # Inicializa el menú
        self.initMenubar()

        # Visor de las imágenes (imagen y control van en el mismo layout)
        # NOTA: Es el objeto central del objeto QMainWindow, que tiene eso, una barra de estado, etc. Podemos volver al QWidget si es fuese mejor.
        self.imageViewer = QWidget(self)
        self.imageViewer.setLayout(QGridLayout())
        # Fija márgenes para centrar la imagen
        self.imageViewer.layout().setColumnStretch(0, 0)
        self.imageViewer.layout().setColumnStretch(2, 0)
        self.imageViewer.layout().setRowStretch(1, 0)
        self.imageViewer.layout().setRowStretch(3, 0)
        # Crea un campo de texto para mostrar el nombre de la imagen
        self.imageName = QLineEdit("No project loaded")
        self.imageName.setReadOnly(True)
        self.imageViewer.layout().addWidget(self.imageName, 0, 1)
        # Crea un objeto de la clase ImageView para mostrar la imagen y dibujar
        self.imageView = ImageView()
        self.imageViewer.layout().addWidget(self.imageView, 2, 1)
        # Inicializa los botones de control
        self.initControlLayout()
        self.imageViewer.layout().addLayout(self.control_layout, 3, 0, 1, 3)
        # Lo situa como objeto pricipal de la aplicación.
        self.setCentralWidget(self.imageViewer)

        # NOTA: Como inicialmente no hay proyecto abierto, deshabilita los botones.
        self.enableControls(False)

    def initMenubar(self):
        '''
        Crea el menú de la aplicación y lo almacena en self.menuBar
        '''
        self.menuBar = QMenuBar()
        self.setMenuBar(self.menuBar)
        self.menuBar.setNativeMenuBar(
            False)  # Necesario para que funcione en MacOS

        # Menu File
        fileMenu = self.menuBar.addMenu("File")
        openAction = QAction('Open image sequence', self)
        fileMenu.addAction(openAction)
        openAction.triggered.connect(self.open)
        exitAction = QAction('Exit', self)
        fileMenu.addAction(exitAction)
        exitAction.triggered.connect(self.close)

        # Menu Display
        displayMenu = self.menuBar.addMenu("Display")
        gen3DAction = QAction('Generate 3D structure', self)
        displayMenu.addAction(gen3DAction)
        gen3DAction.triggered.connect(self.gen3D)

        # Help Display
        helpMenu = self.menuBar.addMenu("Help")
        aboutAction = QAction("About", self)
        helpMenu.addAction(aboutAction)
        # aboutAction.triggered.connect(self.about)  # Una ventana que muestre tu nombre, y eso.

    def initControlLayout(self):
        '''
        Añade los botones para navegar sobre las imágenes en un imgViewerLayout
        denominado self.control_layout.
        '''

        # Alante y atrás
        self.btn_next = QPushButton()
        self.btn_next.setIcon(QIcon('resources/next.png'))
        self.btn_next.setFixedWidth(50)
        self.btn_prev = QPushButton()
        self.btn_prev.setIcon(QIcon('resources/back.png'))
        self.btn_prev.setFixedWidth(50)

        # Borrar y deshacer
        self.btn_clear = QPushButton("Clear")
        self.btn_clear.setFixedWidth(80)
        self.btn_undo = QPushButton("Undo")
        self.btn_undo.setFixedWidth(80)

        # Mostrar o no información de las imágenes anteriores.
        self.check_showC = QCheckBox("Previous Image Curves")
        self.check_showP = QCheckBox("Previous Image Particles")
        self.check_showC.setChecked(False)
        self.check_showP.setChecked(False)

        # Panel para colocar los controles.
        self.control_layout = QHBoxLayout()

        # Coloca los controles en el imgViewerLayout
        self.control_layout.addWidget(self.btn_prev)
        self.control_layout.addWidget(self.btn_next)
        self.control_layout.addStretch()
        self.control_layout.addWidget(self.check_showC)
        self.control_layout.addWidget(self.check_showP)
        self.control_layout.addWidget(self.btn_undo)
        self.control_layout.addWidget(self.btn_clear)

        # Conecta los componentes con las acciones correspondientes.
        self.btn_next.clicked.connect(self.next)
        self.btn_prev.clicked.connect(self.prev)
        self.btn_clear.clicked.connect(self.clear)
        self.btn_undo.clicked.connect(self.undo)
        #self.check_showC.clicked.connect(self.showC)
        #self.check_showP.clicked.connect(self.showP)

    def enableControls(self, state):
        '''
            Habilita o deshabilita los controles y la vista de la imagen.
        '''
        self.imageName.setEnabled(state)
        self.imageView.setEnabled(state)
        self.btn_next.setEnabled(state)
        self.btn_prev.setEnabled(state)
        self.btn_clear.setEnabled(state)
        self.btn_undo.setEnabled(state)
        self.check_showC.setEnabled(state)
        self.check_showP.setEnabled(state)

    def updateWindowSize(self):
        '''
            Aujsta el tamaño de la ventana y la centra
        '''
        # Calcula el tamaño ideal para la vista y la ventana. Para ello determina, el ratio
        # en función la máxima altura o anchura que puede tener la imagen.
        if not self.project is None:
            ratioWidth = (screenSize.getCoords()[2] -
                          100) / (self.project.imgShape[1])
            ratioHeight = (screenSize.getCoords()[3] -
                           150) / (self.project.imgShape[0])
            ratio = ratioWidth if ratioWidth < ratioHeight else ratioHeight
            self.imageView.setFixedWidth(int(self.project.imgShape[1] * ratio))
            self.imageView.setFixedHeight(int(self.project.imgShape[0] *
                                              ratio))
            # Ajusta el tamaño de la ventana.
            self.adjustSize()

        # Centra la ventana
        windowPosition = self.geometry()
        windowPosition.moveCenter(screenSize.center())
        self.move(windowPosition.topLeft())

    def updateImageView(self):
        '''
            Actualiza la imagen
        '''
        # Actualiza el texto y la imagen (recortada).
        self.imageName.setText(
            self.project.imgSequence[self.project.currentImgId])
        utils.cropImageBorders(
            self.project.folder + '/' +
            self.project.imgSequence[self.project.currentImgId])
        self.imageView.loadImage(
            self.project.folder + '/' +
            self.project.imgSequence[self.project.currentImgId])

    def open(self):
        '''
        Abre un proyecto.
        '''
        # Selecciona un directorio de trabajo para cargarlo en un proyecto.
        selectedDirectory = str(
            QFileDialog.getExistingDirectory(self, "Select directory"))

        # Vuelve si se ha cancelado la apertura.
        if len(selectedDirectory) == 0:
            # NOTA: Fíjate que lo que hacemos es dejarlo como estaba. Si había cargado un proyecto, se queda
            #       abierto y los botones y eso habilitados. Si no había nada abierto, sigue sin abrirse.
            return

        # NOTA: Solamente llega aquí si se ha seleccionado un directorio.
        # Se crea el proyecto
        self.project = Project(selectedDirectory)

        # Si en la carpeta seleccionada no hay ninguna imagen, deshabilitamos
        if len(self.project.imgSequence) == 0:
            #self.imageView.scene.clear()
            self.enableControls(False)
            return

        # NOTA: Solamente llega aquí si el proyecto tiene imágenes

        # Actualiza el tamaño de la ventana.
        self.updateWindowSize()

        # Muestra la información actual del proyecto.
        self.updateImageView()

        # Habilita los controles.
        self.enableControls(True)

    def next(self):
        '''
        Pasa a la siguiente imagen.
        '''
        self.project.next()
        self.updateImageView()

    def prev(self):
        '''
        Pasa a la imagen anterior.
        '''
        self.project.prev()
        self.updateImageView()

    def undo(self):
        self.imageView.removeLastCurve()

    def clear(self):
        self.imageView.clear()

    def gen3D(self):
        '''
        Genera la reconstrucción 3D
        '''
        pass
Esempio n. 17
0
class Example(QWidget):
    def __init__(self):
        super().__init__()

        self.filenames = json_files()

        if type(self.filenames) is list:
            self.curr_file = self.filenames[0]
        else:
            self.curr_file = self.filenames

        self.initUI()

    def initUI(self):

        self.num = -1  # index for search bar query
        self.show_save = False  # bool for showing unsaved changes dialog
        self.temp_file = ".temp.csv"
        self.refresh_file = False  # failsafe 1 for itemChanged trigger

        self.list_1 = QListWidget()

        lister(file=self.curr_file, target=self.list_1, index=0, mode=0)
        self.list_1.clicked.connect(self.clear_selection)
        self.list_1.installEventFilter(self)

        self.list_items = self.list_1.count(
        )  # failsafe 2 for itemChanged trigger
        self.list_1.itemChanged.connect(self.edit_next_item)
        self.list_1.verticalScrollBar().valueChanged.connect(self.sync_scroll)

        self.list_2 = QListWidget()
        lister(file=self.curr_file, target=self.list_2, index=1, mode=0)
        self.list_2.clicked.connect(self.clear_selection)

        self.list_3 = QListWidget()
        lister(file=self.curr_file, target=self.list_3, index=2, mode=0)
        self.list_3.clicked.connect(self.clear_selection)

        self.all_lists = [self.list_1, self.list_2, self.list_3]

        self.menubar = QMenuBar()
        self.menubar.setNativeMenuBar(False)

        exit_event = QAction('Exit', self)
        exit_event.setShortcut('Ctrl+W')
        exit_event.triggered.connect(app.quit)

        showAct = QAction('Show extras', self, checkable=True)
        showAct.setChecked(False)
        showAct.setShortcut('Ctrl+E')
        showAct.triggered.connect(self.hide_notes)

        addAct = QAction('Fields', self)
        addAct.setShortcut('Ctrl+N')
        addAct.triggered.connect(self.add_item)

        fileOpen = QAction('Open file', self)
        fileOpen.triggered.connect(self.fileDialog)
        fileOpen.setShortcut('Ctrl+O')

        fileSave = QAction('Save file', self)
        fileSave.triggered.connect(self.save)
        fileSave.triggered.connect(self.refresh_recents)
        fileSave.setShortcut('Ctrl+S')

        self.fileRecents = QMenu('Recent file', self)
        self.refresh_recents()

        self.toggle_theme = QAction('Toggle theme', self, checkable=True)
        self.toggle_theme.setChecked(json_theme())
        self.toggle_theme.triggered.connect(self.theme)
        self.toggle_theme.setShortcut('Ctrl+T')

        self.col_sort_index = QMenu('Sorting column index', self)
        self.col_sort_index.addAction(QAction(str(0), self))
        self.col_sort_index.addAction(QAction(str(1), self))
        self.col_sort_index.addAction(QAction(str(2), self))
        self.col_sort_index.triggered.connect(self.sort_col_choice)

        self.col_search_index = QMenu('Searching column index', self)
        self.col_search_index.addAction(QAction(str(0), self))
        self.col_search_index.addAction(QAction(str(1), self))
        self.col_search_index.addAction(QAction(str(2), self))
        self.col_search_index.triggered.connect(self.search_col_choice)

        self.sort = QAction('Sort entries', self, checkable=True)
        self.curr_col = 0
        self.search_col = 0
        self.sort.triggered.connect(self.refresh_list)
        self.sort.setShortcut('Ctrl+R')

        self.addFields = self.menubar.addMenu('Add')
        self.addFields.addAction(addAct)

        self.optionMenu = self.menubar.addMenu('Options')
        self.optionMenu.addAction(exit_event)
        self.optionMenu.addAction(showAct)
        self.optionMenu.addAction(self.toggle_theme)
        self.optionMenu.addMenu(self.col_sort_index)
        self.optionMenu.addMenu(self.col_search_index)
        self.optionMenu.addAction(self.sort)

        self.fileMenu = self.menubar.addMenu('File')
        self.fileMenu.addAction(fileOpen)
        self.fileMenu.addAction(fileSave)
        self.fileMenu.addMenu(self.fileRecents)

        self.search_bar = QLineEdit()
        self.search_bar.setPlaceholderText('Search vocab')
        self.search_bar.setClearButtonEnabled(True)
        self.search_bar.setMaxLength(10)
        self.search_bar.returnPressed.connect(self.search_item)

        self.status_bar = QStatusBar()
        status(self.status_bar, self.list_1)

        grid = QGridLayout()
        grid.setSpacing(10)
        grid.addWidget(self.menubar, 0, 0)
        grid.addWidget(self.list_1, 1, 0)
        grid.addWidget(self.list_2, 1, 1)
        grid.addWidget(self.list_3, 1, 2)
        grid.addWidget(self.search_bar, 0, 1)
        grid.addWidget(self.status_bar)

        self.theme()
        self.setLayout(grid)
        self.setGeometry(*json_window_size())
        self.setWindowTitle(f'{split_name(self.curr_file)}')
        self.show()

        self.list_1.scrollToBottom()
        self.list_2.verticalScrollBar().setHidden(True)
        self.list_3.verticalScrollBar().setHidden(True)
        self.list_3.setHidden(True)

    def sync_scroll(self):

        scroll_location = self.list_1.verticalScrollBar().value()

        self.list_2.verticalScrollBar().setValue(scroll_location)
        self.list_3.verticalScrollBar().setValue(scroll_location)

    def edit_next_item(self, event):
        """When an item is added and edited on the first col, starts editing its counterpart on the next col"""

        if self.list_items == self.list_1.count(
        ) - 2 or self.list_items != self.list_1.count(
        ) and self.refresh_file == False:

            item = self.list_2.item(self.list_2.count() - 1)
            self.list_2.editItem(item)

            self.list_items = self.list_1.count()

    def closeEvent(self, event):
        """Triggered upon program exit, shows a dialog for unsaved changes using a bool"""

        if self.show_save == True:

            reply = QMessageBox.question(
                self, 'Message',
                "You may have unsaved changes, are you sure you want to quit?",
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

            if reply == QMessageBox.Yes:
                try:
                    remove(self.temp_file)
                except:
                    pass

                event.accept()
            else:
                event.ignore()

        else:
            pass

    def sort_col_choice(self, action):
        self.curr_col = int(action.text())

    def search_col_choice(self, action):
        self.search_col = int(action.text())

    def refresh_list(self):
        """Refreshes the contents of the lists, when sorting is used"""

        self.save(
            mode=1
        )  # saves a temp copy, with changes, but irreversable sorting introduced

        clear_lists(self.all_lists)

        if self.sort.isChecked() == True:
            mode = 2
        else:
            mode = 0

        try:
            lister(file=self.temp_file,
                   target=self.list_1,
                   index=0,
                   mode=mode,
                   column=self.curr_col)
            lister(file=self.temp_file,
                   target=self.list_2,
                   index=1,
                   mode=mode,
                   column=self.curr_col)
            lister(file=self.temp_file,
                   target=self.list_3,
                   index=2,
                   mode=mode,
                   column=self.curr_col)

        except:
            lister(file=self.curr_file,
                   target=self.list_1,
                   index=0,
                   mode=mode,
                   column=self.curr_col)
            lister(file=self.curr_file,
                   target=self.list_2,
                   index=1,
                   mode=mode,
                   column=self.curr_col)
            lister(file=self.curr_file,
                   target=self.list_3,
                   index=2,
                   mode=mode,
                   column=self.curr_col)

    def refresh_recents(self):

        try:

            file_1 = QAction(self.curr_file, self)
            self.fileRecents.addAction(file_1)
            file_1.triggered.connect(self.clickedFileAct)

            if type(self.filenames) is list:

                if self.filenames[1] != None:
                    file_2 = QAction(self.filenames[1], self)
                    self.fileRecents.addAction(file_2)
                    file_2.triggered.connect(self.clickedFileAct)

                if self.filenames[2] != None:
                    file_3 = QAction(self.filenames[2], self)
                    self.fileRecents.addAction(file_3)
                    file_3.triggered.connect(self.clickedFileAct)

        except:
            pass

    def clickedFileAct(self):

        self.refresh_file = True

        file = self.sender().text()
        self.curr_file = file
        self.setWindowTitle(f'{split_name(self.curr_file)}')

        clear_lists(self.all_lists)

        lister(file=self.curr_file, target=self.list_1, index=0)
        lister(file=self.curr_file, target=self.list_2, index=1)
        lister(file=self.curr_file, target=self.list_3, index=2)

        status(self.status_bar, self.list_1)
        self.theme()

        self.list_1.scrollToBottom()
        self.list_3.setHidden(True)

        self.refresh_file = False

    def eventFilter(self, source, event):
        """Item (row) deletion"""

        if (event.type() == QEvent.ContextMenu and source is self.list_1):
            menu = QMenu()
            menu.addAction("Delete row")
            if menu.exec_(event.globalPos()):
                item = source.itemAt(event.pos())
                try:
                    model = self.list_1.indexFromItem(item)
                    row = model.row()

                    self.show_save = True

                    self.list_1.takeItem(row)
                    self.list_2.takeItem(row)
                    self.list_3.takeItem(row)

                    status(self.status_bar, self.list_1,
                           f'Deleted row number: {row+1}.')
                    self.clearSelection()

                except:
                    pass

            return True
        return super(Example, self).eventFilter(source, event)

    def hide_notes(self):
        """Toggles showing the note column and stretches the window for clearer reading of it"""

        self.list_3.setHidden(not self.list_3.isHidden())

    def theme(self):
        """Sets the theme for the window and its widgets"""

        palette = QPalette()

        # dark theme
        if self.toggle_theme.isChecked() == True:

            palette.setColor(QPalette.Window, QColor(0, 0, 0))
            dark = "background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);"

            self.menubar.setStyleSheet(dark)
            self.addFields.setStyleSheet(dark)
            self.optionMenu.setStyleSheet(dark)
            self.fileMenu.setStyleSheet(dark)
            self.search_bar.setStyleSheet(
                "background-color: rgb(0, 0, 0); color: rgb(255, 255, 255)"
            )  # border: 0px; for transparency
            self.status_bar.setStyleSheet(dark)

            style_items(self.all_lists, dark_theme=True)

        # light theme
        elif self.toggle_theme.isChecked() == False:

            palette.setColor(QPalette.Window, QColor(255, 255, 255))
            light = "background-color: rgb(255, 255, 255); color: rgb(0, 0, 0)"

            self.menubar.setStyleSheet(light)
            self.addFields.setStyleSheet(light)
            self.optionMenu.setStyleSheet(light)
            self.fileMenu.setStyleSheet(light)
            self.search_bar.setStyleSheet(light)
            self.status_bar.setStyleSheet(light)

            style_items(self.all_lists, dark_theme=False)

        self.setPalette(palette)

        self.theme_bool = self.toggle_theme.isChecked(
        )  # used in the save func

    def search_item(self):
        """Takes input from the search bar and matches with an item, 
		gets index and scrolls to it, more reusults being qued with the num class var
		"""

        query = self.search_bar.text()
        search = self.all_lists[self.search_col].findItems(
            query, Qt.MatchContains)
        status(self.status_bar, self.list_1, f'Found {len(search)} results.')
        self.clear_selection()

        # testing search in all column

        # search_list =[]
        # for x in range(3):
        # 	search_list.append(self.all_lists[x].findItems(query, Qt.MatchContains))

        # parent_list = []
        # for x in range(3):
        # 	for y in range(len(search_list[x])):
        # 		parent_list.append(self.all_lists[x]) # replace with x

        # import itertools
        # merged = list(itertools.chain.from_iterable(search_list))

        # search_dict = dict(zip(parent_list, merged))
        # print(search_dict)
        # print()
        # print(len(merged))
        # print(len(parent_list))

        self.num += 1
        for i in search:

            try:
                model_index = self.all_lists[self.search_col].indexFromItem(
                    search[self.num])

            except:
                self.num = 0
                model_index = self.all_lists[self.search_col].indexFromItem(
                    search[self.num])

            item_index = model_index.row()

            self.all_lists[self.search_col].item(item_index).setSelected(True)
            self.list_1.scrollToItem(self.list_1.item(item_index),
                                     QAbstractItemView.PositionAtCenter)

    def add_item(self):

        self.show_save = True

        for x in range(3):
            if x == 0:
                lister(file=self.curr_file,
                       target=self.list_1,
                       index=x,
                       mode=1)

            elif x == 1:
                lister(file=self.curr_file,
                       target=self.list_2,
                       index=x,
                       mode=1)

            elif x == 2:
                lister(file=self.curr_file,
                       target=self.list_3,
                       index=x,
                       mode=1)

        item = self.list_1.item(self.list_1.count() - 1)
        self.list_1.editItem(item)
        status(self.status_bar, self.list_1)

        self.list_1.scrollToBottom()
        self.list_2.scrollToBottom()
        self.list_3.scrollToBottom()

    def clear_selection(self):
        """Clears all item slections for aesthetical purposes, but only single clicks"""

        self.list_1.clearSelection()
        self.list_2.clearSelection()
        self.list_3.clearSelection()

    def fileDialog(self):

        fname = QFileDialog()
        path = fname.getOpenFileName(self,
                                     'Open file',
                                     getcwd(),
                                     filter='csv (*.csv);;')
        if path[0] == '':  # failsafe for canceling the dialog
            return self.curr_file

        self.curr_file = path[0]
        self.setWindowTitle(f'{split_name(self.curr_file)}')

        clear_lists(self.all_lists)

        lister(file=self.curr_file, target=self.list_1, index=0)
        lister(file=self.curr_file, target=self.list_2, index=1)
        lister(file=self.curr_file, target=self.list_3, index=2)

        status(self.status_bar, self.list_1)
        self.theme()

    def save(self, mode=0):

        self.show_save = False

        list1_items = items_text(self.list_1)
        list2_items = items_text(self.list_2)
        list3_items = items_text(self.list_3)

        total_dicts = []
        for (a, b, c) in zip(list1_items, list2_items,
                             list3_items):  # each letter is a column
            dictionary = {'word_1': a, 'word_2': b, 'notes': c}
            total_dicts.append(dictionary)

        if mode == 0:

            writer(file=self.curr_file, data=total_dicts)
            status(self.status_bar, self.list_1, ('Saved current changes.'))

            try:
                json_template(theme=self.theme_bool,
                              files=[self.curr_file, None, None],
                              window_size=self.geometry().getRect()
                              )  # current size values of the window

            except:
                json_template(
                )  # bug cannot be avoided, even though used setChecked at the beggining

        elif mode == 1:

            self.show_save = True
            writer(file=self.temp_file, data=total_dicts)

        # avoids stacking and refreshes recent file actions
        actions = self.fileRecents.actions()
        for action in actions:
            self.fileRecents.removeAction(action)
Esempio n. 18
0
class VGenesTextMain(QMainWindow):
    def __init__(self):
        super(VGenesTextMain, self).__init__()
        self.setupUi()

    def setupUi(self):

        self.curFile = ''

        self.textEdit = QTextEdit()
        self.textEdit.setTextInteractionFlags(Qt.TextEditorInteraction)
        self.setCentralWidget(self.textEdit)

        #self.textEdit_legend = QTextEdit()

        #grid = QGridLayout()
        #grid.setSpacing(10)
        #grid.addWidget(self.textEdit, 1, 0)
        #grid.addWidget(self.textEdit_legend, 1, 1)

        #self.setLayout(grid)

        #vbox = QVBoxLayout()
        #vbox.addStretch(1)
        #vbox.addLayout(self.textEdit)
        #vbox.addLayout(self.textEdit_legend)
        #self.setLayout(vbox)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()

        self.readSettings()

        self.textEdit.document().contentsChanged.connect(
            self.documentWasModified)

        self.setCurrentFile('')

    def closeEvent(self, event):
        if self.maybeSave():
            self.writeSettings()
            event.accept()
        else:
            event.ignore()

    def newFile(self):
        if self.maybeSave():
            self.textEdit.clear()
            self.setCurrentFile('')

    def open(self):
        if self.maybeSave():
            fileName, _ = QFileDialog.getOpenFileName(self)
            if fileName:
                self.loadFile(fileName)

    def print_(self):
        document = self.textEdit.document()
        printer = QPrinter()

        dlg = QPrintDialog(printer, self)
        if dlg.exec_() != QDialog.Accepted:
            return

        document.print_(printer)

        self.statusBar().showMessage("Ready", 2000)

    def save(self):
        if self.curFile:
            return self.saveFile(self.curFile)

        return self.saveAs()

    def saveAs(self):
        fileName, _ = QFileDialog.getSaveFileName(self)
        if fileName:
            return self.saveFile(fileName)

        return False

    def IncreaseFont(self):
        FontIs = self.textEdit.currentFont()
        font = QFont(FontIs)

        FontSize = int(font.pointSize())
        FontFam = font.family()
        if FontSize < 36:
            FontSize += 1
        font.setPointSize(FontSize)
        font.setFamily(FontFam)

        self.textEdit.setFont(font)

    def DecreaseFont(self):
        FontIs = self.textEdit.currentFont()
        font = QFont(FontIs)

        FontSize = int(font.pointSize())
        FontFam = font.family()
        if FontSize > 6:
            FontSize -= 1
        font.setPointSize(FontSize)
        font.setFamily(FontFam)

        self.textEdit.setFont(font)

    def legend_act(self):
        pass

    def about(self):
        QMessageBox.about(
            self, "About VGenes Text Editor",
            "The <b>VGenes Text Editor</b> allows "
            "you to edit, save, and print documents "
            "generated by VGenes.")

    def documentWasModified(self):
        self.setWindowModified(self.textEdit.document().isModified())

    def createActions(self):
        self.newAct = QAction(QIcon(':/PNG-Icons/page.png'),
                              "&New",
                              self,
                              shortcut=QKeySequence.New,
                              statusTip="Create a new file",
                              triggered=self.newFile)

        self.openAct = QAction(QIcon(':/PNG-Icons/folder.png'),
                               "&Open...",
                               self,
                               shortcut=QKeySequence.Open,
                               statusTip="Open an existing file",
                               triggered=self.open)

        self.saveAct = QAction(QIcon(':/PNG-Icons/SaveIcon.png'),
                               "&Save",
                               self,
                               shortcut=QKeySequence.Save,
                               statusTip="Save the document to disk",
                               triggered=self.save)

        self.saveAsAct = QAction(
            "Save &As...",
            self,
            shortcut=QKeySequence.SaveAs,
            statusTip="Save the document under a new name",
            triggered=self.saveAs)

        self.closeAct = QAction("Close",
                                self,
                                shortcut=QKeySequence.Close,
                                statusTip="Close window",
                                triggered=self.close)

        self.exitAct = QAction("E&xit",
                               self,
                               shortcut="Ctrl+Q",
                               statusTip="Exit VGenes Text Editor",
                               triggered=self.close)

        self.cutAct = QAction(
            QIcon(':/PNG-Icons/scissor.png'),
            "Cu&t",
            self,
            shortcut=QKeySequence.Cut,
            statusTip="Cut the current selection's contents to the clipboard",
            triggered=self.textEdit.cut)

        self.IncreaseAct = QAction(QIcon(':/PNG-Icons/plus.png'),
                                   "&Increase",
                                   self,
                                   statusTip="Increase font size",
                                   triggered=self.IncreaseFont)

        self.DecreaseAct = QAction(QIcon(':/PNG-Icons/minus.png'),
                                   "&Decrease",
                                   self,
                                   statusTip="Decrease font size",
                                   triggered=self.DecreaseFont)

        self.printAct = QAction(QIcon(':/PNG-Icons/print.png'),
                                "&Print...",
                                self,
                                shortcut=QKeySequence.Print,
                                statusTip="Print the current form letter",
                                triggered=self.print_)

        self.copyAct = QAction(
            QIcon(':/PNG-Icons/pages.png'),
            "&Copy",
            self,
            shortcut=QKeySequence.Copy,
            statusTip="Copy the current selection's contents to the clipboard",
            triggered=self.textEdit.copy)

        self.pasteAct = QAction(
            QIcon(':/PNG-Icons/Paste.png'),
            "&Paste",
            self,
            shortcut=QKeySequence.Paste,
            statusTip=
            "Paste the clipboard's contents into the current selection",
            triggered=self.textEdit.paste)

        self.aboutAct = QAction("&About",
                                self,
                                statusTip="Show the application's About box",
                                triggered=self.about)

        self.Legend = QAction(QIcon(':/PNG-Icons/ScalePic.png'),
                              "&Legend",
                              self,
                              statusTip="Legend",
                              triggered=self.legend_act)

        # self.aboutQtAct = QAction("About &Qt", self,
        #         statusTip="Show the Qt library's About box",
        #         triggered=QApplication.instance().aboutQt)

        self.cutAct.setEnabled(False)
        self.copyAct.setEnabled(False)
        self.textEdit.copyAvailable.connect(self.cutAct.setEnabled)
        self.textEdit.copyAvailable.connect(self.copyAct.setEnabled)

    def createMenus(self):

        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QRect(0, 0, 1029, 22))
        self.menubar.setDefaultUp(False)
        self.menubar.setNativeMenuBar(False)
        self.menubar.setObjectName("menubar")
        self.menuFile = QMenu(self.menubar)

        self.setMenuBar(self.menubar)

        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.closeAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addAction(self.printAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAct)

        self.editMenu = self.menuBar().addMenu("&Edit")
        self.editMenu.addAction(self.cutAct)
        self.editMenu.addAction(self.copyAct)
        self.editMenu.addAction(self.pasteAct)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)
        # self.helpMenu.addAction(self.aboutQtAct)

    def createToolBars(self):
        self.fileToolBar = self.addToolBar("File")
        self.fileToolBar.addAction(self.newAct)
        self.fileToolBar.addAction(self.openAct)
        self.fileToolBar.addAction(self.closeACT)
        self.fileToolBar.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileToolBar.addAction(self.printAct)

        self.editToolBar = self.addToolBar("Edit")
        self.editToolBar.addAction(self.cutAct)
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.pasteAct)

        #self.FontSizeToolBar = self.addToolBar("FontSize")
        #self.FontSizeToolBar.addAction(self.IncreaseAct)
        #self.FontSizeToolBar.addAction(self.DecreaseAct)

        self.LegendToolBar = self.addToolBar("Legend")
        self.LegendToolBar.addAction(self.Legend)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings("Trolltech", "VGenes Text Editor")
        pos = settings.value("pos", QPoint(200, 200))
        size = settings.value("size", QSize(400, 400))
        self.resize(size)
        self.move(pos)

    def writeSettings(self):
        settings = QSettings("Trolltech", "VGenes Text Editor")
        settings.setValue("pos", self.pos())
        settings.setValue("size", self.size())

    def maybeSave(self):
        if self.textEdit.document().isModified():
            ret = QMessageBox.warning(
                self, "VGenes Text Editor",
                "The document has been modified.\nDo you want to save "
                "your changes?",
                QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)

            if ret == QMessageBox.Save:
                return self.save()

            if ret == QMessageBox.Cancel:
                return False

        return True

    def loadFile(self, fileName):
        file = QFile(fileName)
        if not file.open(QFile.ReadOnly | QFile.Text):
            QMessageBox.warning(
                self, "VGenes Text Editor",
                "Cannot read file %s:\n%s." % (fileName, file.errorString()))
            return

        inf = QTextStream(file)
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.textEdit.setPlainText(inf.readAll())
        QApplication.restoreOverrideCursor()

        self.setCurrentFile(fileName)
        self.statusBar().showMessage("File loaded", 2000)

    def saveFile(self, fileName):
        file = QFile(fileName)
        if not file.open(QFile.WriteOnly | QFile.Text):
            QMessageBox.warning(
                self, "VGenes Text Editor",
                "Cannot write file %s:\n%s." % (fileName, file.errorString()))
            return False

        outf = QTextStream(file)
        QApplication.setOverrideCursor(Qt.WaitCursor)
        outf << self.textEdit.toPlainText()
        QApplication.restoreOverrideCursor()

        self.setCurrentFile(fileName)
        self.statusBar().showMessage("File saved", 2000)
        return True

    def setCurrentFile(self, fileName):
        self.curFile = fileName
        self.textEdit.document().setModified(False)
        self.setWindowModified(False)

        if self.curFile:
            shownName = self.strippedName(self.curFile)
        else:
            shownName = 'untitled.txt'

        self.setWindowTitle("%s[*] - VGenes Text Editor" % shownName)

    def strippedName(self, fullFileName):
        return QFileInfo(fullFileName).fileName()
Esempio n. 19
0
class VGenesTextMain(QMainWindow):
    def __init__(self):
        super(VGenesTextMain, self).__init__()
        self.setupUi()

    def setupUi(self):

        self.curFile = ''

        self.textEdit = QTextEdit()
        self.textEdit.setTextInteractionFlags(Qt.TextEditorInteraction)
        self.setCentralWidget(self.textEdit)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()

        self.readSettings()

        self.textEdit.document().contentsChanged.connect(self.documentWasModified)

        self.setCurrentFile('')

    def closeEvent(self, event):
        if self.maybeSave():
            self.writeSettings()
            event.accept()
        else:
            event.ignore()

    def newFile(self):
        if self.maybeSave():
            self.textEdit.clear()
            self.setCurrentFile('')

    def open(self):
        if self.maybeSave():
            fileName, _ = QFileDialog.getOpenFileName(self)
            if fileName:
                self.loadFile(fileName)

    def print_(self):
        document = self.textEdit.document()
        printer = QPrinter()

        dlg = QPrintDialog(printer, self)
        if dlg.exec_() != QDialog.Accepted:
            return

        document.print_(printer)

        self.statusBar().showMessage("Ready", 2000)

    def save(self):
        if self.curFile:
            return self.saveFile(self.curFile)

        return self.saveAs()

    def saveAs(self):
        fileName, _ = QFileDialog.getSaveFileName(self)
        if fileName:
            return self.saveFile(fileName)

        return False

    def IncreaseFont(self):
        FontIs = self.textEdit.currentFont()
        font = QFont(FontIs)

        FontSize = int(font.pointSize())
        FontFam = font.family()
        if FontSize < 36:
            FontSize += 1
        font.setPointSize(FontSize)
        font.setFamily(FontFam)

        self.textEdit.setFont(font)

    def DecreaseFont(self):
        FontIs = self.textEdit.currentFont()
        font = QFont(FontIs)

        FontSize = int(font.pointSize())
        FontFam = font.family()
        if FontSize > 6:
            FontSize -= 1
        font.setPointSize(FontSize)
        font.setFamily(FontFam)

        self.textEdit.setFont(font)

    def about(self):
        QMessageBox.about(self, "About VGenes Text Editor",
                "The <b>VGenes Text Editor</b> allows "
                "you to edit, save, and print documents "
                "generated by VGenes.")

    def documentWasModified(self):
        self.setWindowModified(self.textEdit.document().isModified())

    def createActions(self):
        self.newAct = QAction(QIcon(':/PNG-Icons/page.png'), "&New", self,
                shortcut=QKeySequence.New, statusTip="Create a new file",
                triggered=self.newFile)

        self.openAct = QAction(QIcon(':/PNG-Icons/folder.png'), "&Open...", self,
                shortcut=QKeySequence.Open, statusTip="Open an existing file",
                triggered=self.open)

        self.saveAct = QAction(QIcon(':/PNG-Icons/SaveIcon.png'), "&Save", self,
                shortcut=QKeySequence.Save,
                statusTip="Save the document to disk", triggered=self.save)

        self.saveAsAct = QAction("Save &As...", self,
                shortcut=QKeySequence.SaveAs,
                statusTip="Save the document under a new name",
                triggered=self.saveAs)

        self.closeAct = QAction("Close", self, shortcut=QKeySequence.Close,
                statusTip="Close window", triggered=self.close)

        self.exitAct = QAction("E&xit", self, shortcut="Ctrl+Q",
                statusTip="Exit VGenes Text Editor", triggered=self.close)



        self.cutAct = QAction(QIcon(':/PNG-Icons/scissor.png'), "Cu&t", self,
                shortcut=QKeySequence.Cut,
                statusTip="Cut the current selection's contents to the clipboard",
                triggered=self.textEdit.cut)

        self.IncreaseAct = QAction(QIcon(':/PNG-Icons/plus.png'), "&Increase", self,
                statusTip="Increase font size",
                triggered=self.IncreaseFont)

        self.DecreaseAct = QAction(QIcon(':/PNG-Icons/minus.png'), "&Decrease", self,
                statusTip="Decrease font size",
                triggered=self.DecreaseFont)

        self.printAct = QAction(QIcon(':/PNG-Icons/print.png'), "&Print...", self,
                shortcut=QKeySequence.Print,
                statusTip="Print the current form letter",
                triggered=self.print_)

        self.copyAct = QAction(QIcon(':/PNG-Icons/pages.png'), "&Copy", self,
                shortcut=QKeySequence.Copy,
                statusTip="Copy the current selection's contents to the clipboard",
                triggered=self.textEdit.copy)

        self.pasteAct = QAction(QIcon(':/PNG-Icons/Paste.png'), "&Paste", self,
                shortcut=QKeySequence.Paste,
                statusTip="Paste the clipboard's contents into the current selection",
                triggered=self.textEdit.paste)

        self.aboutAct = QAction("&About", self,
                statusTip="Show the application's About box",
                triggered=self.about)

        # self.aboutQtAct = QAction("About &Qt", self,
        #         statusTip="Show the Qt library's About box",
        #         triggered=QApplication.instance().aboutQt)

        self.cutAct.setEnabled(False)
        self.copyAct.setEnabled(False)
        self.textEdit.copyAvailable.connect(self.cutAct.setEnabled)
        self.textEdit.copyAvailable.connect(self.copyAct.setEnabled)

    def createMenus(self):

        self.menubar = QMenuBar(self)
        self.menubar.setGeometry(QRect(0, 0, 1029, 22))
        self.menubar.setDefaultUp(False)
        self.menubar.setNativeMenuBar(False)
        self.menubar.setObjectName("menubar")
        self.menuFile = QMenu(self.menubar)


        self.setMenuBar(self.menubar)



        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.closeAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addAction(self.printAct)
        self.fileMenu.addSeparator();
        self.fileMenu.addAction(self.exitAct)

        self.editMenu = self.menuBar().addMenu("&Edit")
        self.editMenu.addAction(self.cutAct)
        self.editMenu.addAction(self.copyAct)
        self.editMenu.addAction(self.pasteAct)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)
        # self.helpMenu.addAction(self.aboutQtAct)

    def createToolBars(self):
        self.fileToolBar = self.addToolBar("File")
        self.fileToolBar.addAction(self.newAct)
        self.fileToolBar.addAction(self.openAct)
        self.fileToolBar.addAction(self.closeACT)
        self.fileToolBar.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileToolBar.addAction(self.printAct)

        self.editToolBar = self.addToolBar("Edit")
        self.editToolBar.addAction(self.cutAct)
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.pasteAct)

        self.FontSizeToolBar = self.addToolBar("FontSize")
        self.FontSizeToolBar.addAction(self.IncreaseAct)
        self.FontSizeToolBar.addAction(self.DecreaseAct)


    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings("Trolltech", "VGenes Text Editor")
        pos = settings.value("pos", QPoint(200, 200))
        size = settings.value("size", QSize(400, 400))
        self.resize(size)
        self.move(pos)

    def writeSettings(self):
        settings = QSettings("Trolltech", "VGenes Text Editor")
        settings.setValue("pos", self.pos())
        settings.setValue("size", self.size())

    def maybeSave(self):
        if self.textEdit.document().isModified():
            ret = QMessageBox.warning(self, "VGenes Text Editor",
                    "The document has been modified.\nDo you want to save "
                    "your changes?",
                    QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)

            if ret == QMessageBox.Save:
                return self.save()

            if ret == QMessageBox.Cancel:
                return False

        return True

    def loadFile(self, fileName):
        file = QFile(fileName)
        if not file.open(QFile.ReadOnly | QFile.Text):
            QMessageBox.warning(self, "VGenes Text Editor",
                    "Cannot read file %s:\n%s." % (fileName, file.errorString()))
            return

        inf = QTextStream(file)
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.textEdit.setPlainText(inf.readAll())
        QApplication.restoreOverrideCursor()

        self.setCurrentFile(fileName)
        self.statusBar().showMessage("File loaded", 2000)

    def saveFile(self, fileName):
        file = QFile(fileName)
        if not file.open(QFile.WriteOnly | QFile.Text):
            QMessageBox.warning(self, "VGenes Text Editor",
                    "Cannot write file %s:\n%s." % (fileName, file.errorString()))
            return False

        outf = QTextStream(file)
        QApplication.setOverrideCursor(Qt.WaitCursor)
        outf << self.textEdit.toPlainText()
        QApplication.restoreOverrideCursor()

        self.setCurrentFile(fileName);
        self.statusBar().showMessage("File saved", 2000)
        return True

    def setCurrentFile(self, fileName):
        self.curFile = fileName
        self.textEdit.document().setModified(False)
        self.setWindowModified(False)

        if self.curFile:
            shownName = self.strippedName(self.curFile)
        else:
            shownName = 'untitled.txt'

        self.setWindowTitle("%s[*] - VGenes Text Editor" % shownName)

    def strippedName(self, fullFileName):
        return QFileInfo(fullFileName).fileName()