diff --git a/MSMD_multiLevel.py b/MSMD_multiLevel.py index 0e9fa3a..e884851 100644 --- a/MSMD_multiLevel.py +++ b/MSMD_multiLevel.py @@ -20,6 +20,7 @@ Version History: import sys import os import time +from pathlib import Path from PyQt5.QtWidgets import (QApplication, QWidget, QLineEdit, QFileDialog, QPushButton, QLabel, QHBoxLayout, QVBoxLayout, QMessageBox, QStackedLayout, QGraphicsScene, QGraphicsView, QDesktopWidget, QGraphicsEllipseItem, @@ -36,10 +37,42 @@ try: import pyautogui except : pass -import pyaudio +import pyaudio import wave -import glob - +import glob + +def getUserConfigDir(): + """Get the platform-specific user configuration directory.""" + if sys.platform == 'darwin': # macOS + config_dir = Path.home() / 'Library' / 'Application Support' / 'MSMD' + elif sys.platform == 'win32': # Windows + config_dir = Path(os.environ.get('APPDATA', Path.home())) / 'MSMD' + else: # Linux and others + config_dir = Path.home() / '.config' / 'MSMD' + + # Create directory if it doesn't exist + config_dir.mkdir(parents=True, exist_ok=True) + return config_dir + +def getConfigFilePath(): + """Get the full path to the config file in the user directory.""" + return getUserConfigDir() / 'config.ini' + +def createDefaultConfig(): + """Create a default config.ini file if it doesn't exist.""" + config_path = getConfigFilePath() + if not config_path.exists(): + default_config = """[robot] +upgradetrigger = hotspot +upgrademode = both +minpowertomove = 55 +maxpowertomove = 95 +showReferenceCreator = 0 +""" + config_path.write_text(default_config) + print(f'Created default config at: {config_path}') + return config_path + textToScanCodeTable = {} def buildScanCodeTranslationTable (hotSpotDict): for imageName,metadata in hotSpotDict.items(): @@ -243,23 +276,28 @@ class App(QWidget): def readConfig(self): + # Create default config if it doesn't exist + config_path = createDefaultConfig() + self.configFilePath = str(config_path) + self.config = configparser.ConfigParser() - fileCheck = self.config.read('config.ini') + fileCheck = self.config.read(self.configFilePath) if(fileCheck == []): - QMessageBox.critical(self, 'Config Error!', 'config.ini was not found', QMessageBox.Ok) + QMessageBox.critical(self, 'Config Error!', f'config.ini was not found at {self.configFilePath}', QMessageBox.Ok) self.robotSettings = self.config['robot'] self.upgradeTrigger = self.robotSettings['upgradeTrigger'] self.upgradeMode = self.robotSettings['upgradeMode'] self.minPowerToMove = self.robotSettings['minPowerToMove'] self.maxPowerToMove = self.robotSettings['maxPowerToMove'] - self.showReferenceCreator = int(self.robotSettings.get('showReferenceCreator', '1')) + self.showReferenceCreator = int(self.robotSettings.get('showReferenceCreator', '0')) def writeConfig(self): self.robotSettings['upgradeTrigger'] = self.upgradeTrigger self.robotSettings['upgradeMode'] = self.upgradeMode self.robotSettings['minPowerToMove'] = self.minPowerToMove self.robotSettings['maxPowerToMove'] = self.maxPowerToMove - with open('config.ini', 'w') as configFile: + self.robotSettings['showReferenceCreator'] = str(self.showReferenceCreator) + with open(self.configFilePath, 'w') as configFile: self.config.write(configFile) def openSettings(self): @@ -285,7 +323,11 @@ class App(QWidget): self.upgradeMode = newSettings['upgradeMode'] self.minPowerToMove = newSettings['minPowerToMove'] self.maxPowerToMove = newSettings['maxPowerToMove'] + self.showReferenceCreator = int(newSettings['showReferenceCreator']) self.writeConfig() + # Update reference creator button visibility if it exists + if hasattr(self, 'referenceCreator'): + self.referenceCreator.setVisible(self.showReferenceCreator == 1) else: print ('ERROR - Unknown message returned from Settings.py Window!') self.setDisabled(False) diff --git a/README.md b/README.md index c7ef45e..ee2caa0 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,30 @@ Add sound effects by placing WAV files named `sound0.wav`, `sound1.wav`, etc., i ## Configuration -Edit `config.ini` to customize robot behavior: +MSMD Player stores its configuration in a platform-specific user directory: + +- **macOS**: `~/Library/Application Support/MSMD/config.ini` +- **Windows**: `%APPDATA%\MSMD\config.ini` +- **Linux**: `~/.config/MSMD/config.ini` + +A default configuration file is automatically created on first run. + +### Changing Settings + +**Option 1: Settings Dialog (Recommended)** + +Click the Settings button (gear icon) in the main window to open the Settings dialog. All configuration options can be changed through the UI: +- Upgrade Trigger (Hotspot or Level) +- Upgrade Mode (Both, Left, Right, or Distance) +- Minimum Power to Move (0-255) +- Maximum Power to Move (0-255) +- Show Reference Creator checkbox + +Changes are saved immediately when you click "Set". + +**Option 2: Manual Edit** + +You can also manually edit the `config.ini` file: ```ini [robot] @@ -162,6 +185,8 @@ maxpowertomove = 95 # Maximum power (0-255) showReferenceCreator = 0 # Show reference creator button (0 or 1) ``` +Restart the application for manual changes to take effect. + ### Configuration Options - **upgradetrigger**: When to upgrade robot power @@ -361,7 +386,11 @@ See project repository for license information. ## Troubleshooting ### "Config.ini was not found" -Create a `config.ini` file in the project root using the configuration template above. +This error should not occur as the config file is created automatically on first run. If you see this error: +- Check that the application has write permissions to the user config directory +- On macOS: `~/Library/Application Support/MSMD/` +- On Windows: `%APPDATA%\MSMD\` +- On Linux: `~/.config/MSMD/` ### "hotspots.json does not exist" Ensure your content folder contains a valid `hotspots.json` file with entries for each image. diff --git a/Settings.py b/Settings.py index 764fc9e..750fd6c 100644 --- a/Settings.py +++ b/Settings.py @@ -7,7 +7,7 @@ Created on Fri Apr 20 18:11:20 2018 from PyQt5.QtCore import Qt, pyqtSignal from PyQt5.QtGui import QIcon -from PyQt5.QtWidgets import (QHBoxLayout, QVBoxLayout, QGridLayout, QComboBox, QLabel, QSpinBox, QGroupBox, QPushButton, QWidget, QFrame, QSpacerItem, QSizePolicy) +from PyQt5.QtWidgets import (QHBoxLayout, QVBoxLayout, QGridLayout, QComboBox, QLabel, QSpinBox, QGroupBox, QPushButton, QWidget, QFrame, QSpacerItem, QSizePolicy, QCheckBox) class QHLine(QFrame): def __init__(self): @@ -76,7 +76,11 @@ class Settings(QWidget): self.MaxPower.setSingleStep(5) self.MaxPower.setFixedWidth(60) self.MaxPower.setValue(int(SettingsIn['maxPowerToMove'])) - + + self.ShowReferenceCreator = QCheckBox() + self.ShowReferenceCreator.setToolTip('Show the "Create Reference" button in the main window') + self.ShowReferenceCreator.setChecked(int(SettingsIn.get('showReferenceCreator', '0')) == 1) + SetButton = QPushButton() SetButton.setToolTip('Use the current settings') SetButton.setText('Set') @@ -115,12 +119,18 @@ class Settings(QWidget): hlayout1.addWidget(UpgradeFrame) hlayout1.addWidget(SpeedFrame) - + + hlayoutRefCreator = QHBoxLayout() + hlayoutRefCreator.addWidget(QLabel('Show Reference Creator:')) + hlayoutRefCreator.addWidget(self.ShowReferenceCreator) + hlayoutRefCreator.addStretch(1) + hlayout2.addStretch(1) hlayout2.addWidget(SetButton) hlayout2.addWidget(CancelButton) vlayout3.addLayout(hlayout1) + vlayout3.addLayout(hlayoutRefCreator) vlayout3.addStretch(1) vlayout3.addWidget(QHLine()) vlayout3.addLayout(hlayout2) @@ -131,7 +141,8 @@ class Settings(QWidget): out = {'upgradeTrigger': str(self.UpgradeTrigger.currentText()).lower(), 'upgradeMode': str(self.UpgradeMode.currentText()).lower(), 'minPowerToMove': str(self.MinPower.value()), - 'maxPowerToMove': str(self.MaxPower.value())} + 'maxPowerToMove': str(self.MaxPower.value()), + 'showReferenceCreator': '1' if self.ShowReferenceCreator.isChecked() else '0'} return(out) #==============================================================================