From 4b2bc7f91fb2144d3637d033b833840a3665de6f Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Wed, 29 Mar 2023 14:07:19 +0300 Subject: [PATCH] EnvVars: Handle environment variables with a QAbstractTableModel Using a ChainMap and this custom model, we can display global environ variables in the per-game settings, allowin better overview and simpler override. --- .../tabs/settings/widgets/env_vars.py | 359 ++++-------------- .../tabs/settings/widgets/env_vars_model.py | 269 +++++++++++++ .../tabs/settings/widgets/env_vars.py | 64 ---- .../tabs/settings/widgets/env_vars.ui | 79 ---- 4 files changed, 336 insertions(+), 435 deletions(-) create mode 100644 rare/components/tabs/settings/widgets/env_vars_model.py delete mode 100644 rare/ui/components/tabs/settings/widgets/env_vars.py delete mode 100644 rare/ui/components/tabs/settings/widgets/env_vars.ui diff --git a/rare/components/tabs/settings/widgets/env_vars.py b/rare/components/tabs/settings/widgets/env_vars.py index 00e68833..e6a679ea 100644 --- a/rare/components/tabs/settings/widgets/env_vars.py +++ b/rare/components/tabs/settings/widgets/env_vars.py @@ -1,310 +1,85 @@ from logging import getLogger -from PyQt5.QtCore import Qt, QFileSystemWatcher -from PyQt5.QtGui import QFont -from PyQt5.QtWidgets import QGroupBox, QTableWidgetItem, QMessageBox, QPushButton, QHeaderView, QFrame +from PyQt5.QtCore import QFileSystemWatcher +from PyQt5.QtWidgets import ( + QGroupBox, + QHeaderView, + QVBoxLayout, + QTableView, +) from rare.shared import LegendaryCoreSingleton -from rare.ui.components.tabs.settings.widgets.env_vars import Ui_EnvVars -from rare.utils import config_helper -from rare.utils.misc import icon +from .env_vars_model import EnvVarsTableModel logger = getLogger("EnvVars") -class EnvVars(QGroupBox, Ui_EnvVars): +class EnvVars(QGroupBox): def __init__(self, parent): super(EnvVars, self).__init__(parent=parent) - self.setupUi(self) - self.app_name = None + self.setTitle(self.tr("Environment variables")) + self.core = LegendaryCoreSingleton() - self.latest_item = None - self.list_of_readonly = [ - "STEAM_COMPAT_DATA_PATH", - "STEAM_COMPAT_CLIENT_INSTALL_PATH", - "WINEPREFIX", - "DXVK_HUD", - "MANGOHUD_CONFIG", - ] - self.warn_msg = self.tr("Readonly, please edit this via the appropriate setting above.") - self.setup_file_watcher() - self.env_vars_table.cellChanged.connect(self.update_env_vars) - self.env_vars_table.verticalHeader().sectionClicked.connect(self.remove_row) - # We use this function to keep an eye on the config. - # When the user uses for example the wineprefix settings, we need to update the table. - # With this function, when the config file changes, we update the table. - def setup_file_watcher(self): + self.table_model = EnvVarsTableModel(self.core) + self.table_view = QTableView(self) + self.table_view.setModel(self.table_model) + self.table_view.verticalHeader().sectionPressed.disconnect() + self.table_view.horizontalHeader().sectionPressed.disconnect() + self.table_view.verticalHeader().sectionClicked.connect(self.table_model.removeRow) + self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) + self.table_view.horizontalHeader().setStretchLastSection(True) + self.table_view.setCornerButtonEnabled(False) + + # FIXME: investigate signaling between widgets + # We use this function to keep an eye on the config. + # When the user uses for example the wineprefix settings, we need to update the table. + # With this function, when the config file changes, we update the table. self.config_file_watcher = QFileSystemWatcher([str(self.core.lgd.config_path)], self) - self.config_file_watcher.fileChanged.connect(self.import_env_vars) + self.config_file_watcher.fileChanged.connect(self.table_model.reset) - def append_row(self): - # If the last row is not None, we insert a new one and set the correct icon. - row_count = self.env_vars_table.rowCount() + row_height = self.table_view.rowHeight(0) + self.table_view.setMinimumHeight(row_height * 7) - if row_count == 0: - self.env_vars_table.insertRow(0) - trash_icon = QTableWidgetItem() - trash_icon.setIcon(icon("mdi.delete", "ei.minus")) - self.env_vars_table.setVerticalHeaderItem(row_count, trash_icon) - return + layout = QVBoxLayout(self) + layout.addWidget(self.table_view) - last_item = self.env_vars_table.item(self.env_vars_table.rowCount() - 1, 0) - - if last_item is not None: - self.env_vars_table.insertRow(row_count) - trash_icon = QTableWidgetItem() - trash_icon.setIcon(icon("mdi.delete", "ei.minus")) - self.env_vars_table.setVerticalHeaderItem(row_count, trash_icon) - - def import_env_vars(self): - self.env_vars_table.blockSignals(True) - self.env_vars_table.clearContents() - - # If the config file doesnt have an env var section, we just set RowCount to 1 and return. - if not self.core.lgd.config.has_section(f"{self.app_name}.env"): - self.env_vars_table.setRowCount(1) - trash_icon = QTableWidgetItem() - trash_icon.setIcon(icon("mdi.delete", "ei.minus")) - self.env_vars_table.setVerticalHeaderItem(0, trash_icon) - self.env_vars_table.blockSignals(False) - return - - # We count how many keys we have and insert new lines - # (as many as we need). - self.env_vars_table.setRowCount(len(self.core.lgd.config[f"{self.app_name}.env"]) + 1) - - # Each iteration we have to create a new QTableWidgetItem object, - # else we segfault. (For using the same object in multiple references.) - for i, (key, value) in enumerate(self.core.lgd.config[f"{self.app_name}.env"].items()): - trash_icon = QTableWidgetItem() - trash_icon.setIcon(icon("mdi.delete", "ei.minus")) - self.env_vars_table.setVerticalHeaderItem(i, trash_icon) - - font = QFont("Monospace") - font.setStyleHint(QFont.Monospace) - - key_item = QTableWidgetItem() - key_item.setText(key) - key_item.setFont(font) - self.env_vars_table.setItem(i, 0, key_item) - - value_item = QTableWidgetItem() - value_item.setFont(font) - value_item.setText(value) - self.env_vars_table.setItem(i, 1, value_item) - if key in self.list_of_readonly: - key_item.setFlags(key_item.flags() ^ Qt.ItemIsEnabled) - key_item.setToolTip(self.warn_msg) - - value_item.setFlags(value_item.flags() ^ Qt.ItemIsEnabled) - value_item.setToolTip(self.warn_msg) - - trash_icon = QTableWidgetItem() - trash_icon.setIcon(icon("mdi.delete", "ei.minus")) - self.env_vars_table.setVerticalHeaderItem(self.env_vars_table.rowCount() - 1, trash_icon) - self.env_vars_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) - - self.env_vars_table.blockSignals(False) - - def update_env_vars(self, row, column): - self.config_file_watcher.removePath(str(self.core.lgd.config_path)) - row_count = self.env_vars_table.rowCount() - key_item = self.env_vars_table.item(row, 0) - value_item = self.env_vars_table.item(row, 1) - - if key_item is not None and not key_item.text(): - try: - list_of_config_keys = list(self.core.lgd.config[f"{self.app_name}.env"].keys()) - except KeyError: - list_of_config_keys = [] - try: - config_helper.remove_option(f"{self.app_name}.env", list_of_config_keys[row]) - except IndexError: - # Item hasnt been saved to the config yet. - pass - self.env_vars_table.removeRow(key_item.row()) - self.append_row() - return - - # get all config keys - try: - list_of_config_keys = list(self.core.lgd.config[f"{self.app_name}.env"].keys()) - except KeyError: - list_of_config_keys = [] - - # get all table keys - list_of_keys_in_table = [] - for i in range(row_count): - item = self.env_vars_table.item(i, 0) - if item: - list_of_keys_in_table.append(item.text()) - - missing_item = list(set(list_of_config_keys) - set(list_of_keys_in_table)) - if len(missing_item) != 0: - config_helper.remove_option(f"{self.app_name}.env", missing_item[0]) - - # A env var always needs to have a key. - # If it's none, we return. - if key_item is None: - return - - if key_item.text() in self.list_of_readonly: - error_dialog = QMessageBox() - error_dialog.setText( - self.tr("Please don't manually add this environment variable. Use the appropriate game setting above.")) - error_dialog.exec() - key_item.setText("") - if value_item is not None: - value_item.setText("") - config_helper.remove_option(f"{self.app_name}.env", key_item.text()) - return - - if key_item.text(): - if "=" in key_item.text(): - error_dialog = QMessageBox() - error_dialog.setText( - self.tr("Please don't use an equal sign in an env var.")) - error_dialog.exec() - self.env_vars_table.removeRow(row) - self.append_row() - return - - if key_item.text() in list_of_config_keys and column == 0: - ask_user = QMessageBox() - ask_user.setText( - self.tr("The config already contains this environment variable.")) - ask_user.setInformativeText( - self.tr("Do you want to keep the newer one or the older one?")) - - ask_user.addButton(QPushButton("Keep the newer one"), QMessageBox.YesRole) - ask_user.addButton(QPushButton("Keep the older one"), QMessageBox.NoRole) - - response = ask_user.exec() - - if response == 0: - if value_item is not None: - config_helper.add_option(f"{self.app_name}.env", key_item.text(), value_item.text()) - else: - config_helper.add_option(f"{self.app_name}.env", key_item.text(), "") - - item_to_safe = self.env_vars_table.findItems(key_item.text(), Qt.MatchExactly) - - # aznd: - # This is to fix an issue where the user updates a env var, thats above the older one. - # so say if you have two env vars: - # something = newkey - # yes = oldkey - # if the user updates the something key to yes, it would delete the wrong row, - # since item_to_safe[0] is the first search result. but we dont want to delete that, - # we want to delete the second result. - # we use this simple if check to find out which case we have. - if key_item.row() < item_to_safe[0].row(): - self.env_vars_table.removeRow(item_to_safe[0].row()) - elif key_item.row() > item_to_safe[0].row(): - self.env_vars_table.removeRow(item_to_safe[0].row()) - else: - self.env_vars_table.removeRow(item_to_safe[1].row()) - - self.append_row() - return - - elif response == 1: - self.env_vars_table.removeRow(row) - self.append_row() - return - - # When the value_item is None, we just use an empty string for the value. - if value_item is None: - if self.latest_item in list_of_config_keys: - config_helper.remove_option(f"{self.app_name}.env", self.latest_item) - config_helper.save_config() - - config_helper.add_option(f"{self.app_name}.env", key_item.text(), "") - config_helper.save_config() - else: - if self.latest_item in list_of_config_keys: - config_helper.remove_option(f"{self.app_name}.env", self.latest_item) - config_helper.save_config() - - config_helper.add_option( - f"{self.app_name}.env", - key_item.text(), - value_item.text() - ) - config_helper.save_config() - - self.append_row() - self.config_file_watcher.addPath(str(self.core.lgd.config_path)) - - def remove_row(self, index): - self.config_file_watcher.removePath(str(self.core.lgd.config_path)) - key_item = self.env_vars_table.item(index, 0) - value_item = self.env_vars_table.item(index, 1) - - if key_item is None: - if value_item is not None: - value_item.setText("") - return - - # If the user tries to delete one of the readonly vars, we return immediately. - if key_item.text() in self.list_of_readonly: - return - - if key_item is not None: - self.env_vars_table.removeRow(index) - try: - list_of_keys = [] - for key in self.core.lgd.config[f"{self.app_name}.env"]: - list_of_keys.append(key) - config_helper.remove_option(f"{self.app_name}.env", list_of_keys[index]) - except (KeyError, IndexError): - pass - self.config_file_watcher.addPath(str(self.core.lgd.config_path)) - - def check_if_item(self, item: QTableWidgetItem) -> bool: - item_to_check = self.env_vars_table.findItems(item.text(), Qt.MatchExactly) - if item_to_check[0].column() == 0: - return False - return True - - def keyPressEvent(self, e): - if e.key() == Qt.Key_Delete or e.key() == Qt.Key_Backspace: - selected_items = self.env_vars_table.selectedItems() - - if len(selected_items) == 0: - return - - item_in_table = self.env_vars_table.findItems(selected_items[0].text(), Qt.MatchExactly) - - # Our first selection is in column 0. So, we have to find out if the user - # only selected keys, or keys and values. we use the check_if_item func - if item_in_table[0].column() == 0: - which_index_to_use = 1 - if len(selected_items) == 1: - which_index_to_use = 0 - if self.check_if_item(selected_items[which_index_to_use]): - # User selected keys and values, so we skip the values - for i in selected_items[::2]: - if i: - config_helper.remove_option(f"{self.app_name}.env", i.text()) - self.env_vars_table.removeRow(i.row()) - self.append_row() - else: - # user only selected keys - for i in selected_items: - if i: - config_helper.remove_option(f"{self.app_name}.env", i.text()) - self.env_vars_table.removeRow(i.row()) - self.append_row() - - # User only selected values, so we just set the text to "" - elif item_in_table[0].column() == 1: - [i.setText("") for i in selected_items] - - elif e.key() == Qt.Key_Escape: - e.ignore() + # def keyPressEvent(self, e): + # if e.key() == Qt.Key_Delete or e.key() == Qt.Key_Backspace: + # selected_items = self.ui.env_vars_table.selectedItems() + # + # if len(selected_items) == 0: + # return + # + # item_in_table = self.ui.env_vars_table.findItems(selected_items[0].text(), Qt.MatchExactly) + # + # # Our first selection is in column 0. So, we have to find out if the user + # # only selected keys, or keys and values. we use the check_if_item func + # if item_in_table[0].column() == 0: + # which_index_to_use = 1 + # if len(selected_items) == 1: + # which_index_to_use = 0 + # if self.check_if_item(selected_items[which_index_to_use]): + # # User selected keys and values, so we skip the values + # for i in selected_items[::2]: + # if i: + # config_helper.remove_option(f"{self.app_name}.env", i.text()) + # self.ui.env_vars_table.removeRow(i.row()) + # self.append_row() + # else: + # # user only selected keys + # for i in selected_items: + # if i: + # config_helper.remove_option(f"{self.app_name}.env", i.text()) + # self.ui.env_vars_table.removeRow(i.row()) + # self.append_row() + # + # # User only selected values, so we just set the text to "" + # elif item_in_table[0].column() == 1: + # [i.setText("") for i in selected_items] + # + # elif e.key() == Qt.Key_Escape: + # e.ignore() def update_game(self, app_name): - self.app_name = app_name - self.import_env_vars() + self.table_model.load(app_name) diff --git a/rare/components/tabs/settings/widgets/env_vars_model.py b/rare/components/tabs/settings/widgets/env_vars_model.py new file mode 100644 index 00000000..cf545388 --- /dev/null +++ b/rare/components/tabs/settings/widgets/env_vars_model.py @@ -0,0 +1,269 @@ +import re +import sys +from collections import ChainMap +from pprint import pprint +from typing import Any, Union + +from rare.utils.misc import icon +from PyQt5.QtCore import Qt, QModelIndex, QAbstractTableModel, pyqtSlot +from PyQt5.QtGui import QFont +from PyQt5.QtWidgets import QTableView, QHeaderView, QApplication, QDialog, QVBoxLayout +from legendary.core import LegendaryCore + + +class EnvVarsTableModel(QAbstractTableModel): + def __init__(self, core: LegendaryCore, parent = None): + super(EnvVarsTableModel, self).__init__(parent=parent) + self.core = core + + self.__validator = re.compile(r"(^[A-Za-z_][A-Za-z0-9_]*)") + self.__data_map: ChainMap = ChainMap() + + self.__readonly = [ + "STEAM_COMPAT_DATA_PATH", + "STEAM_COMPAT_CLIENT_INSTALL_PATH", + "WINEPREFIX", + "DXVK_HUD", + "MANGOHUD_CONFIG", + ] + + self.__default: str = "default" + self.__appname: str = None + + @pyqtSlot(str) + def reset(self): + if not self.__appname: + return + self.load(self.__appname) + + def load(self, app_name: str): + self.__appname = app_name + self.beginResetModel() + if not self.core.lgd.config.has_section(f"{self.__appname}.env"): + self.core.lgd.config[f"{self.__appname}.env"] = {} + self.__data_map = ChainMap( + self.core.lgd.config[f"{self.__appname}.env"], + self.core.lgd.config[f"{self.__default}.env"] if self.__appname != self.__default else {} + ) + self.endResetModel() + + def __key(self, index: Union[QModelIndex, int]): + if isinstance(index, QModelIndex): + index = index.row() + try: + return list(self.__data_map)[index] + except Exception as e: + print(e, index) + return "" + + def __is_local(self, index: Union[QModelIndex, int]): + key = self.__key(index) + return key in self.__data_map.maps[0].keys() + + def __is_global(self, index: Union[QModelIndex, int]): + key = self.__key(index) + return key in self.__data_map.maps[1].keys() + + def __is_readonly(self, index: Union[QModelIndex, int]): + key = self.__key(index) + return key in self.__readonly + + def __value(self, index: Union[QModelIndex, int]): + if isinstance(index, QModelIndex): + index = index.row() + return self.__data_map[self.__key(index)] + + def __title(self, section: int): + if section == 0: + return self.tr("Key") + elif section == 1: + return self.tr("Value") + + def __data_length(self): + return len(self.__data_map) + + def __is_key_valid(self, value: str): + match = self.__validator.match(value) + if not match: + return False + return value == match.group(0) + + def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any: + if role == Qt.DisplayRole or role == Qt.EditRole: + if index.row() == self.__data_length(): + return "" + if index.column() == 0: + return self.__key(index) + else: + return self.__value(index) + + if role == Qt.TextAlignmentRole: + if index.column() == 0: + return Qt.AlignVCenter + Qt.AlignRight + else: + return Qt.AlignVCenter + Qt.AlignLeft + + if role == Qt.FontRole: + font = QFont("Monospace") + font.setStyleHint(QFont.Monospace) + if index.row() < self.__data_length() and not self.__is_local(index): + font.setWeight(QFont.Bold) + else: + font.setWeight(QFont.Normal) + return font + + if role == Qt.ToolTipRole: + if index.row() == self.__data_length(): + if index.column() == 1: + return self.tr("Disabled, please set the variable name first.") + else: + return None + if self.__key(index) in self.__readonly: + return self.tr("Readonly, please edit this via setting the appropriate setting.") + + def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.DisplayRole) -> Any: + if role == Qt.DisplayRole: + if orientation == Qt.Horizontal: + return self.__title(section) + if role == Qt.DecorationRole: + if orientation == Qt.Vertical: + if section < self.__data_length() and not self.__is_readonly(section): + if self.__is_global(section) and self.__is_local(section): + return icon("mdi.refresh-circle", "ei.refresh") + if self.__is_local(section): + return icon("mdi.delete", "ei.remove-sign") + return icon("mdi.lock", "ei.lock") + if role == Qt.TextAlignmentRole: + return Qt.AlignVCenter + Qt.AlignHCenter + return None + + def flags(self, index: QModelIndex): + # Disable the value cell on rows without a name + if index.row() == self.__data_length(): + if index.column() == 1: + return super().flags(index) ^ Qt.ItemIsEnabled + else: + return Qt.ItemIsEditable | super().flags(index) + + # Disable readonly variables + if self.__is_readonly(index): + return super().flags(index) ^ Qt.ItemIsEnabled + + return Qt.ItemIsEditable | super().flags(index) + + def rowCount(self, parent: QModelIndex = None) -> int: + parent = parent if parent else QModelIndex() + # The length of the outer list. + return self.__data_length() + 1 + + def columnCount(self, parent: QModelIndex = None) -> int: + parent = parent if parent else QModelIndex() + return 2 + + def setData(self, index: QModelIndex, value: Any, role: int = Qt.DisplayRole) -> bool: + if role != Qt.EditRole: + return False + # Do not accept unchanged contents + if index.row() < self.__data_length() and (value == self.__key(index) or value == self.__value(index)): + return False + + # TODO: restrict spaces in variable names + + if index.column() == 0: + if not self.__is_key_valid(value): + return False + # Do not accept existing variable names + if value in self.__data_map.keys(): + return False + else: + if index.row() == self.__data_length(): + self.beginInsertRows(QModelIndex(), self.rowCount(index), self.rowCount(index)) + self.endInsertRows() + self.__data_map[value] = "" + self.core.lgd.save_config() + self.dataChanged.emit(index, index, []) + self.headerDataChanged.emit(Qt.Vertical, index.row(), index.row()) + # if we are on the last row, add a new last row to the table when setting the variable name + else: + # if we are not in the last row, we have to update an existing variable name + old_key = self.__key(index) + self.__data_map[value] = self.__data_map[old_key] + self.core.lgd.save_config() + # since we delete and add a new key, the new key will be moved at the end + # deleting a local key can have the following effects + # unique local key: + # old key deleted, new key added -> update range from index to end + # old local key masking global key: + # old key remains, new key added -> insert row for new key, update from index to end + # new key masking global key: + # can't happen because we do not accept existing keys + if old_key in self.__data_map.maps[0].keys(): + # delete the old key if it is a local one, replacing a local key + del self.__data_map[old_key] + self.core.lgd.save_config() + if old_key in self.__data_map.maps[1].keys(): + self.beginInsertRows(QModelIndex(), self.__data_length(), self.__data_length()) + self.endInsertRows() + self.dataChanged.emit(index, self.index(index.row(), 1), []) + self.dataChanged.emit(self.index(self.__data_length() - 1, 0), self.index(self.__data_length() - 1, 1), []) + self.headerDataChanged.emit(Qt.Vertical, index.row(), index.row()) + self.headerDataChanged.emit(Qt.Vertical, self.__data_length() - 1, self.__data_length() - 1) + else: + self.__data_map[self.__key(index)] = value + self.core.lgd.save_config() + self.dataChanged.emit(self.index(index.row(), 0), index, []) + self.headerDataChanged.emit(Qt.Vertical, index.row(), index.row()) + # pprint([item for item in self.__data_map.items()]) + return True + + def removeRow(self, row: int, parent: QModelIndex = None) -> bool: + parent = parent if parent else QModelIndex() + # Refuse to remove the last row + if row == self.__data_length(): + return False + # Refuse to remove readonly keys + if self.__is_readonly(row): + return False + # Refuse to remove keys that don't have our app_name (in this case the default) + if not self.__is_local(row): + return False + if self.__is_global(row): + del self.__data_map[self.__key(row)] + self.core.lgd.save_config() + self.dataChanged.emit(self.index(row, 0), self.index(row, 1), []) + self.headerDataChanged.emit(Qt.Vertical, row, row) + else: + self.beginRemoveRows(QModelIndex(), row, row) + del self.__data_map[self.__key(row)] + self.core.lgd.save_config() + self.endRemoveRows() + # pprint([item for item in self.__data_map.items()]) + return True + + +class MainDialog(QDialog): + def __init__(self): + super().__init__() + + self.table = QTableView() + self.model = EnvVarsTableModel(LegendaryCore()) + self.model.load("Tamarind") + + self.table.setModel(self.model) + self.table.verticalHeader().sectionPressed.disconnect() + self.table.horizontalHeader().sectionPressed.disconnect() + self.table.verticalHeader().sectionClicked.connect(self.model.removeRow) + self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) + self.table.horizontalHeader().setStretchLastSection(True) + self.table.setCornerButtonEnabled(False) + + self.setLayout(QVBoxLayout(self)) + self.layout().addWidget(self.table) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + window = MainDialog() + window.setFixedSize(800, 600) + window.show() + app.exec() diff --git a/rare/ui/components/tabs/settings/widgets/env_vars.py b/rare/ui/components/tabs/settings/widgets/env_vars.py deleted file mode 100644 index a0a08312..00000000 --- a/rare/ui/components/tabs/settings/widgets/env_vars.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'rare/ui/components/tabs/settings/widgets/env_vars.ui' -# -# Created by: PyQt5 UI code generator 5.15.7 -# -# WARNING: Any manual changes made to this file will be lost when pyuic5 is -# run again. Do not edit this file unless you know what you are doing. - - -from PyQt5 import QtCore, QtGui, QtWidgets - - -class Ui_EnvVars(object): - def setupUi(self, EnvVars): - EnvVars.setObjectName("EnvVars") - EnvVars.resize(592, 200) - EnvVars.setMinimumSize(QtCore.QSize(0, 200)) - EnvVars.setWindowTitle("GroupBox") - self.verticalLayout = QtWidgets.QVBoxLayout(EnvVars) - self.verticalLayout.setContentsMargins(0, -1, 0, 0) - self.verticalLayout.setObjectName("verticalLayout") - self.env_vars_table = QtWidgets.QTableWidget(EnvVars) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.env_vars_table.sizePolicy().hasHeightForWidth()) - self.env_vars_table.setSizePolicy(sizePolicy) - self.env_vars_table.setFrameShape(QtWidgets.QFrame.NoFrame) - self.env_vars_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.env_vars_table.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) - self.env_vars_table.setObjectName("env_vars_table") - self.env_vars_table.setColumnCount(2) - self.env_vars_table.setRowCount(1) - item = QtWidgets.QTableWidgetItem() - item.setText("-") - self.env_vars_table.setVerticalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.env_vars_table.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.env_vars_table.setHorizontalHeaderItem(1, item) - self.env_vars_table.horizontalHeader().setStretchLastSection(True) - self.env_vars_table.verticalHeader().setStretchLastSection(False) - self.verticalLayout.addWidget(self.env_vars_table) - - self.retranslateUi(EnvVars) - - def retranslateUi(self, EnvVars): - _translate = QtCore.QCoreApplication.translate - EnvVars.setTitle(_translate("EnvVars", "Environment variables")) - item = self.env_vars_table.horizontalHeaderItem(0) - item.setText(_translate("EnvVars", "Key")) - item = self.env_vars_table.horizontalHeaderItem(1) - item.setText(_translate("EnvVars", "Value")) - - -if __name__ == "__main__": - import sys - app = QtWidgets.QApplication(sys.argv) - EnvVars = QtWidgets.QGroupBox() - ui = Ui_EnvVars() - ui.setupUi(EnvVars) - EnvVars.show() - sys.exit(app.exec_()) diff --git a/rare/ui/components/tabs/settings/widgets/env_vars.ui b/rare/ui/components/tabs/settings/widgets/env_vars.ui deleted file mode 100644 index 136e9d74..00000000 --- a/rare/ui/components/tabs/settings/widgets/env_vars.ui +++ /dev/null @@ -1,79 +0,0 @@ - - - EnvVars - - - - 0 - 0 - 592 - 200 - - - - - 0 - 200 - - - - GroupBox - - - Environment variables - - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - Qt::ScrollBarAsNeeded - - - QAbstractScrollArea::AdjustToContents - - - true - - - false - - - - - - - - - - Key - - - - - Value - - - - - - - - -