Implement env_vars
This commit is contained in:
parent
324530171e
commit
0f03c06dab
4 changed files with 357 additions and 0 deletions
219
rare/components/tabs/games/env_vars.py
Normal file
219
rare/components/tabs/games/env_vars.py
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
from PyQt5.QtGui import QKeyEvent
|
||||||
|
from PyQt5.QtWidgets import QGroupBox, QTableWidgetItem, QMessageBox
|
||||||
|
import qtawesome
|
||||||
|
from rare.ui.components.tabs.games.env_vars import Ui_EnvVars
|
||||||
|
from rare.utils import config_helper
|
||||||
|
from rare.shared import LegendaryCoreSingleton
|
||||||
|
from PyQt5 import QtCore
|
||||||
|
|
||||||
|
|
||||||
|
class EnvVars(QGroupBox, Ui_EnvVars):
|
||||||
|
def __init__(self, parent):
|
||||||
|
super(EnvVars, self).__init__(parent=parent)
|
||||||
|
self.setupUi(self)
|
||||||
|
self.app_name = None
|
||||||
|
self.core = LegendaryCoreSingleton()
|
||||||
|
self.latest_item = None
|
||||||
|
self.list_of_readonly = ["STEAM_COMPAT_DATA_PATH", "DXVK_HUD", "WINEPREFIX"]
|
||||||
|
self.warn_msg = "Readonly, please edit this via the relative setting."
|
||||||
|
|
||||||
|
def compare_config_and_table(self):
|
||||||
|
list_of_keys_in_table = []
|
||||||
|
row_count = self.env_vars_table.rowCount()
|
||||||
|
|
||||||
|
for i in range(row_count):
|
||||||
|
item = self.env_vars_table.item(i, 0)
|
||||||
|
try:
|
||||||
|
list_of_keys_in_table.append(item.text())
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
list_of_keys_in_config = []
|
||||||
|
try:
|
||||||
|
for key in self.core.lgd.config[f"{self.app_name}.env"]:
|
||||||
|
list_of_keys_in_config.append(key)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def import_env_vars(self):
|
||||||
|
self.env_vars_table.disconnect()
|
||||||
|
self.env_vars_table.clearContents()
|
||||||
|
|
||||||
|
list_of_keys = []
|
||||||
|
list_of_values = []
|
||||||
|
|
||||||
|
# First, we try to get all keys and values from the config
|
||||||
|
try:
|
||||||
|
for key in self.core.lgd.config[f"{self.app_name}.env"]:
|
||||||
|
list_of_keys.append(key)
|
||||||
|
for i in list_of_keys:
|
||||||
|
list_of_values.append(self.core.lgd.config[f"{self.app_name}.env"][i])
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# We count how many keys we have and insert new lines
|
||||||
|
# (as many as we need).
|
||||||
|
# Each iteration we have to create a new QTableWidgetItem object,
|
||||||
|
# else we segfault. (For using the same object in multiple references.)
|
||||||
|
count = len(list_of_keys)
|
||||||
|
for i in range(count):
|
||||||
|
self.env_vars_table.insertRow(i)
|
||||||
|
|
||||||
|
trash_icon = QTableWidgetItem()
|
||||||
|
trash_icon.setIcon(qtawesome.icon("mdi.delete"))
|
||||||
|
self.env_vars_table.setVerticalHeaderItem(i, trash_icon)
|
||||||
|
# We set the row count to the length of the list_of_keys
|
||||||
|
if len(list_of_keys) == 0:
|
||||||
|
self.env_vars_table.setRowCount(1)
|
||||||
|
else:
|
||||||
|
self.env_vars_table.setRowCount(len(list_of_keys))
|
||||||
|
|
||||||
|
for index, val in enumerate(list_of_keys):
|
||||||
|
new_item = QTableWidgetItem()
|
||||||
|
new_item.setText(val)
|
||||||
|
|
||||||
|
if new_item.text() in self.list_of_readonly:
|
||||||
|
new_item.setFlags(new_item.flags() ^ QtCore.Qt.ItemIsEnabled)
|
||||||
|
new_item.setToolTip(self.warn_msg)
|
||||||
|
|
||||||
|
self.env_vars_table.setItem(index, 0, new_item)
|
||||||
|
|
||||||
|
for index, val in enumerate(list_of_values):
|
||||||
|
new_item = QTableWidgetItem()
|
||||||
|
new_item.setText(val)
|
||||||
|
|
||||||
|
# We need to check if the first_item is in the list of readonly vars.
|
||||||
|
# If yes, we also need to disable column 1.
|
||||||
|
first_item = self.env_vars_table.item(index, 0)
|
||||||
|
if first_item.text() in self.list_of_readonly:
|
||||||
|
new_item.setFlags(new_item.flags() ^ QtCore.Qt.ItemIsEnabled)
|
||||||
|
new_item.setToolTip(self.warn_msg)
|
||||||
|
self.env_vars_table.setItem(index, 1, new_item)
|
||||||
|
|
||||||
|
row_count = self.env_vars_table.rowCount()
|
||||||
|
last_item = self.env_vars_table.item(row_count - 1, 0)
|
||||||
|
if last_item is not None:
|
||||||
|
self.env_vars_table.insertRow(row_count)
|
||||||
|
trash_icon = QTableWidgetItem()
|
||||||
|
trash_icon.setIcon(qtawesome.icon("mdi.delete"))
|
||||||
|
self.env_vars_table.setVerticalHeaderItem(row_count, trash_icon)
|
||||||
|
|
||||||
|
new_thing = QTableWidgetItem()
|
||||||
|
new_thing.setIcon(qtawesome.icon("mdi.delete"))
|
||||||
|
self.env_vars_table.setVerticalHeaderItem(0, new_thing)
|
||||||
|
|
||||||
|
self.compare_config_and_table()
|
||||||
|
|
||||||
|
# We need to call this at the end, since at startup we import the
|
||||||
|
# config and update the table. Thus, the cellChanged signal reacts, but
|
||||||
|
# we don't want that. Maybe we should only call this once, at startup?
|
||||||
|
# Like this we always connect at every update_game.
|
||||||
|
self.env_vars_table.cellChanged.connect(self.update_env_vars)
|
||||||
|
self.env_vars_table.verticalHeader().sectionClicked.connect(self.remove_row)
|
||||||
|
|
||||||
|
def update_env_vars(self, row):
|
||||||
|
row_count = self.env_vars_table.rowCount()
|
||||||
|
first_item = self.env_vars_table.item(row, 0)
|
||||||
|
second_item = self.env_vars_table.item(row, 1)
|
||||||
|
|
||||||
|
list_of_keys = []
|
||||||
|
try:
|
||||||
|
for key in self.core.lgd.config[f"{self.app_name}.env"]:
|
||||||
|
list_of_keys.append(key)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
list_of_keys_in_table = []
|
||||||
|
|
||||||
|
for i in range(row_count):
|
||||||
|
item = self.env_vars_table.item(i, 0)
|
||||||
|
try:
|
||||||
|
list_of_keys_in_table.append(item.text())
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
missing_item = list(set(list_of_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 first_item is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if first_item.text() in self.list_of_readonly:
|
||||||
|
error_dialog = QMessageBox()
|
||||||
|
error_dialog.setText("Please don't manually add this environment variable. Use the appropriate game setting above.")
|
||||||
|
error_dialog.exec()
|
||||||
|
first_item.setText("")
|
||||||
|
return
|
||||||
|
|
||||||
|
if first_item.text():
|
||||||
|
# When the second_item is None, we just use an empty string for the value.
|
||||||
|
if second_item is None:
|
||||||
|
if self.latest_item in list_of_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", first_item.text(), "")
|
||||||
|
config_helper.save_config()
|
||||||
|
else:
|
||||||
|
if self.latest_item in list_of_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",
|
||||||
|
first_item.text(),
|
||||||
|
second_item.text()
|
||||||
|
)
|
||||||
|
config_helper.save_config()
|
||||||
|
|
||||||
|
row_count = self.env_vars_table.rowCount()
|
||||||
|
last_item = self.env_vars_table.item(row_count - 1, 0)
|
||||||
|
|
||||||
|
if last_item is not None:
|
||||||
|
if last_item.text():
|
||||||
|
self.env_vars_table.insertRow(row_count)
|
||||||
|
trash_icon = QTableWidgetItem()
|
||||||
|
trash_icon.setIcon(qtawesome.icon("mdi.delete"))
|
||||||
|
self.env_vars_table.setVerticalHeaderItem(row_count, trash_icon)
|
||||||
|
|
||||||
|
def remove_row(self, index):
|
||||||
|
# The user also should be able to delete the row,
|
||||||
|
# even if rowCount() is lower than 1, but then the row
|
||||||
|
# should be just cleared. (And not deleted)
|
||||||
|
|
||||||
|
first_item = self.env_vars_table.item(index, 0)
|
||||||
|
|
||||||
|
# The first item needs to have some text, else we don't delete it.
|
||||||
|
if first_item is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# If the user tries to delete one of the readonly vars, we show a message and return.
|
||||||
|
if first_item.text() in self.list_of_readonly:
|
||||||
|
error_dialog = QMessageBox()
|
||||||
|
error_dialog.setText("Please use the appropriate setting above to remove this key.")
|
||||||
|
error_dialog.exec()
|
||||||
|
return
|
||||||
|
|
||||||
|
if first_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
|
||||||
|
|
||||||
|
def keyPressEvent(self, e):
|
||||||
|
if e.key() == QtCore.Qt.Key_Delete or e.key() == QtCore.Qt.Key_Backspace:
|
||||||
|
selected_items = self.env_vars_table.selectedItems()
|
||||||
|
for i in selected_items:
|
||||||
|
config_helper.remove_option(f"{self.app_name}.env", i.text())
|
||||||
|
self.env_vars_table.removeRow(i.row())
|
||||||
|
|
||||||
|
def update_game(self, app_name):
|
||||||
|
self.app_name = app_name
|
||||||
|
self.import_env_vars()
|
|
@ -5,6 +5,7 @@ from pathlib import Path
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
from PyQt5.QtCore import QSettings, QThreadPool, Qt
|
from PyQt5.QtCore import QSettings, QThreadPool, Qt
|
||||||
|
from PyQt5.QtGui import QKeyEvent
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QWidget,
|
QWidget,
|
||||||
QFileDialog,
|
QFileDialog,
|
||||||
|
@ -19,6 +20,7 @@ from legendary.models.game import InstalledGame, Game
|
||||||
from rare.components.tabs.settings.linux import LinuxSettings
|
from rare.components.tabs.settings.linux import LinuxSettings
|
||||||
from rare.components.tabs.settings.widgets.wrapper import WrapperSettings
|
from rare.components.tabs.settings.widgets.wrapper import WrapperSettings
|
||||||
from rare.ui.components.tabs.games.game_info.game_settings import Ui_GameSettings
|
from rare.ui.components.tabs.games.game_info.game_settings import Ui_GameSettings
|
||||||
|
from rare.components.tabs.games.env_vars import EnvVars
|
||||||
from rare.utils import config_helper
|
from rare.utils import config_helper
|
||||||
from rare.utils.extra_widgets import PathEdit
|
from rare.utils.extra_widgets import PathEdit
|
||||||
from rare.utils.utils import WineResolver, get_raw_save_path
|
from rare.utils.utils import WineResolver, get_raw_save_path
|
||||||
|
@ -141,6 +143,8 @@ class GameSettings(QWidget, Ui_GameSettings):
|
||||||
self.linux_settings.mangohud.set_wrapper_activated.connect(
|
self.linux_settings.mangohud.set_wrapper_activated.connect(
|
||||||
lambda active: self.wrapper_settings.add_wrapper("mangohud")
|
lambda active: self.wrapper_settings.add_wrapper("mangohud")
|
||||||
if active else self.wrapper_settings.delete_wrapper("mangohud"))
|
if active else self.wrapper_settings.delete_wrapper("mangohud"))
|
||||||
|
self.env_vars = EnvVars(self)
|
||||||
|
self.game_settings_contents_layout.addWidget(self.env_vars)
|
||||||
|
|
||||||
def compute_save_path(self):
|
def compute_save_path(self):
|
||||||
if (
|
if (
|
||||||
|
@ -359,8 +363,11 @@ class GameSettings(QWidget, Ui_GameSettings):
|
||||||
self.core.lgd.config.get(self.game.app_name, "override_exe", fallback="")
|
self.core.lgd.config.get(self.game.app_name, "override_exe", fallback="")
|
||||||
)
|
)
|
||||||
self.change = True
|
self.change = True
|
||||||
|
self.env_vars.update_game(app_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LinuxAppSettings(LinuxSettings):
|
class LinuxAppSettings(LinuxSettings):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(LinuxAppSettings, self).__init__()
|
super(LinuxAppSettings, self).__init__()
|
||||||
|
|
64
rare/ui/components/tabs/games/env_vars.py
Normal file
64
rare/ui/components/tabs/games/env_vars.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'rare/ui/components/tabs/games/env_vars.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.6
|
||||||
|
#
|
||||||
|
# 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(720, 561)
|
||||||
|
EnvVars.setMinimumSize(QtCore.QSize(0, 200))
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(EnvVars)
|
||||||
|
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.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()
|
||||||
|
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)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(EnvVars)
|
||||||
|
|
||||||
|
def retranslateUi(self, EnvVars):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
EnvVars.setWindowTitle(_translate("EnvVars", "GroupBox"))
|
||||||
|
EnvVars.setTitle(_translate("EnvVars", "Environment variables"))
|
||||||
|
item = self.env_vars_table.verticalHeaderItem(0)
|
||||||
|
item.setText(_translate("EnvVars", "-"))
|
||||||
|
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_())
|
67
rare/ui/components/tabs/games/env_vars.ui
Normal file
67
rare/ui/components/tabs/games/env_vars.ui
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>EnvVars</class>
|
||||||
|
<widget class="QGroupBox" name="EnvVars">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>720</width>
|
||||||
|
<height>561</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>GroupBox</string>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Environment variables</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="env_vars_table">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderStretchLastSection">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<row>
|
||||||
|
<property name="text">
|
||||||
|
<string>-</string>
|
||||||
|
</property>
|
||||||
|
</row>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Key</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Value</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in a new issue