Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix several bugs found in production #85

Merged
merged 2 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions application/common/game_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ def __init__(self, defaults_dict: dict = {}) -> None:
self._defaults = defaults_dict
self._game_default_install_dir = None

# Whether or not users are alloed to add additional args.
# Allowed by default. Game implementations will have to disable it.
self._allow_user_args = True

if constants.SETTING_NAME_DEFAULT_PATH in self._defaults:
self._game_default_install_dir = defaults_dict[
constants.SETTING_NAME_DEFAULT_PATH
Expand Down
9 changes: 9 additions & 0 deletions application/common/toolbox.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import inspect
import importlib.util
import platform
import psutil
import sys

Expand Down Expand Up @@ -179,3 +180,11 @@ def update_game_state(game_data: dict, new_state: GameStates) -> True:
update_success = False

return update_success


@staticmethod
def _correct_path(path_value):
fixed_path = ""
if platform.system() == "Windows":
fixed_path = path_value.replace("/", "\\")
return fixed_path
3 changes: 3 additions & 0 deletions application/games/seven_dtd_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ def __init__(self, defaults_dict: dict = {}) -> None:
)
)

# The user may not add additional arguments for this game server.
self._allow_user_args = False

def startup(self) -> None:
# Run base class checks
# Run base class checks
Expand Down
43 changes: 35 additions & 8 deletions application/gui/widgets/add_argument_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from PyQt5.QtCore import Qt

from application.common import toolbox
from application.common.constants import FileModes
from application.common.decorators import timeit
from application.gui.widgets.file_select_widget import FileSelectWidget
Expand All @@ -33,22 +34,24 @@ def __init__(self, client: Operator, parent: QWidget = None) -> None:

self._arg_name_edit: QLineEdit = None
self._arg_value_edit: QWidget = None
self._arg_required: QCheckBox = None
self._arg_file_mode_edit: QComboBox = None
self._arg_equals_edit: QCheckBox = None
self._arg_quotes_edit: QCheckBox = None

self._submit_btn: QPushButton = QPushButton("Submit")
self._reset_btn: QPushButton = QPushButton("Reset")

def closeEvent(self, event):
if self._parent:
self._parent.start_timer()

def init_ui(self, game_name: str):
self._layout.setAlignment(Qt.AlignTop)

self._layout.addWidget(QLabel("Add Argument:"), 0, 0)

self._arg_name_edit = QLineEdit()
self._arg_value_edit = QLineEdit()
self._arg_required = QCheckBox()
self._arg_file_mode_edit = QComboBox()
self._arg_equals_edit = QCheckBox()
self._arg_quotes_edit = QCheckBox()
Expand All @@ -64,9 +67,6 @@ def init_ui(self, game_name: str):
self._layout.addWidget(QLabel("Argument Value: "), 2, 0)
self._layout.addWidget(self._arg_value_edit, 2, 1)

self._layout.addWidget(QLabel("Required? "), 3, 0)
self._layout.addWidget(self._arg_required, 3, 1)

self._layout.addWidget(QLabel("File Mode Select: "), 4, 0)
self._layout.addWidget(self._arg_file_mode_edit, 4, 1)

Expand All @@ -89,6 +89,19 @@ def init_ui(self, game_name: str):

self._initialized = True

self.clear()

def clear(self):
self._arg_name_edit.setText("")

if isinstance(self._arg_value_edit, FileSelectWidget):
self._arg_value_edit.get_line_edit().setText("")
else:
self._arg_value_edit.setText("")
self._arg_file_mode_edit.setCurrentIndex(0)
self._arg_equals_edit.setChecked(False)
self._arg_quotes_edit.setChecked(False)

def update(self, game_name: str):
self._game_name = game_name

Expand All @@ -110,13 +123,16 @@ def _update_value_edit(self, file_mode_string: str) -> None:
self.adjustSize()

def _submit_argument(self, game_name: str) -> None:
# For error messages
message = QMessageBox()

# Line edit
arg_name = self._arg_name_edit.text()

# combo
file_mode = self._arg_file_mode_edit.currentIndex()

arg_required = self._arg_required.isChecked()
arg_required = False # User may never add a new required argument.
arg_equals = self._arg_equals_edit.isChecked()
arg_quotes = self._arg_quotes_edit.isChecked()

Expand All @@ -126,6 +142,15 @@ def _submit_argument(self, game_name: str) -> None:
file_mode == FileModes.FILE.value or file_mode == FileModes.DIRECTORY.value
):
arg_value = self._arg_value_edit.get_line_edit().text()
arg_value = toolbox._correct_path(arg_value)

# Check if all args are empty.
if arg_value == "" or arg_name == "":
message.setText("Error: Cannot create an empty argument!")
message.exec()
self.clear()
self._parent.start_timer()
return

argument_id = self._client.game.create_argument(
game_name,
Expand All @@ -138,11 +163,13 @@ def _submit_argument(self, game_name: str) -> None:
use_quotes=arg_quotes,
)

message = QMessageBox()
if argument_id == -1:
message.setText("New Arg: There was an error creating the argument.")
else:
message.setText("Success!")
message.setText("Success! Please wait for user interface to update.")
self.hide()
self._parent._refresh_on_timer()
self._parent.start_timer()
self.clear()

message.exec()
3 changes: 2 additions & 1 deletion application/gui/widgets/file_select_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
)
from PyQt5.QtGui import QFont, QFontMetrics

from application.common import toolbox
from application.common.constants import FileModes
from operator_client import Operator

Expand Down Expand Up @@ -74,7 +75,7 @@ def handle_button(self) -> None:
)

if path:
self._path_line_edit.setText(path)
self._path_line_edit.setText(toolbox._correct_path(path))

def _resize_to_content(self):
text = self._path_line_edit.text()
Expand Down
29 changes: 25 additions & 4 deletions application/gui/widgets/game_arguments_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,23 @@ class GameArgumentsWidget(QWidget):
ARG_ACTION_COL = 3

def __init__(
self, client: Operator, arg_data: dict, parent: QWidget, disable_cols: list = []
self,
client: Operator,
arg_data: dict,
parent: QWidget,
disable_cols: list = [],
built_in_args=None,
) -> None:
super(QWidget, self).__init__(parent)

self._parent = parent
self._client = client
self._layout = QVBoxLayout()
# Args that the game has built in + args the user added.
self._arg_data = arg_data
# Args that the game has built in
self._built_in_args = built_in_args
# Args on this widget
self._args_dict: dict = {}
self._disable_cols = disable_cols

Expand Down Expand Up @@ -131,9 +140,21 @@ def update_arguments_table(self, game_arguments=None):
elif c == self.ARG_REQUIRED_COL:
if "Required" in self._disable_cols:
continue
required_cb = QCheckBox()
required_cb.setChecked(True if arg_required == 1 else False)
self._table.setCellWidget(r, c, required_cb)
# If provided built in args list... check if arg is in that list.
if self._built_in_args:
required_cb = QCheckBox()
required_cb.setChecked(True if arg_required == 1 else False)
self._table.setCellWidget(r, c, required_cb)

# disable the checkbox if the arg isn't in that place.
if arg_name not in self._built_in_args:
required_cb.setDisabled(True)

else:
# otherwise... Just add a checkbox
required_cb = QCheckBox()
required_cb.setChecked(True if arg_required == 1 else False)
self._table.setCellWidget(r, c, required_cb)
elif c == self.ARG_ACTION_COL:
if "Actions" in self._disable_cols:
continue
Expand Down
18 changes: 14 additions & 4 deletions application/gui/widgets/game_manager_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@


class GameManagerWidget(QWidget):
REFRESH_INTERVAL = 15 * constants.MILIS_PER_SECOND
# The lower this number ,the faster it updates.
REFRESH_INTERVAL = 6 * constants.MILIS_PER_SECOND
# Update at this faster interval in certain situations.
FAST_INTERVAL = 1 * constants.MILIS_PER_SECOND

def __init__(self, client: Operator, globals, parent: QWidget) -> None:
Expand All @@ -40,6 +42,8 @@ def __init__(self, client: Operator, globals, parent: QWidget) -> None:
self._add_arguments_widget: AddArgumentWidget = globals._add_arguments_widget
self._current_arg_widget: GameArgumentsWidget = None

self._add_arguments_widget._parent = self

# Primitives
self._installed_supported_games: dict = {}
self._modules_dict: dict = toolbox._find_conforming_modules(games)
Expand Down Expand Up @@ -136,7 +140,7 @@ def update_installed_games(

installed_supported_games = list(self._installed_supported_games.keys())

# Init routine uses this fucntion. Don't want to replace the widget the "first" time.
# Init routine uses this function. Don't want to replace the widget the "first" time.
if len(installed_supported_games) > 0:
new_game_frame = self._build_game_frame(installed_supported_games[0])

Expand Down Expand Up @@ -302,19 +306,24 @@ def _build_game_frame(self, game_name):
game_frame_main_layout.addLayout(h_layout_all_game_info)

# Game Arguments

game_args_label = QLabel("Game Arguments:", game_frame)
game_args_label.setStyleSheet("text-decoration: underline;")
built_in_args = game_object._get_argument_list()
game_args = self._client.game.get_argument_by_game_name(game_object._game_name)
self._current_arg_widget = GameArgumentsWidget(
self._client, game_args, game_frame
self._client, game_args, game_frame, built_in_args=built_in_args
)

game_frame_main_layout.addWidget(game_args_label)
game_frame_main_layout.addWidget(self._current_arg_widget)

# Add argument button
self._add_arg_btn = QPushButton("Add Argument")

# Disable this button if the game server doesn't allow user to add arguments.
if not game_object._allow_user_args:
self._add_arg_btn.setDisabled(True)

game_frame_main_layout.addWidget(self._add_arg_btn)
self._add_arg_btn.clicked.connect(
lambda: self._show_add_argument_widget(self._current_game_name)
Expand Down Expand Up @@ -398,6 +407,7 @@ def _show_add_argument_widget(self, game_name):
self._add_arguments_widget.init_ui(game_name)
else:
self._add_arguments_widget.update(game_name)
self.stop_timer()
self._add_arguments_widget.show()

def _startup_game(self, game_name):
Expand Down
5 changes: 2 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
alembic
concurrent-log-handler
debugpy
flask
Flask-SQLAlchemy
flask==3.0.0
Flask-SQLAlchemy==3.1.1
gunicorn
oauthlib
psutil
Expand Down
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# TODO - Split requirements.txt file up.
black
coverage
debugpy
flake8
pytest
pytest-mock
Loading