Skip to content
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
22 changes: 15 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ jobs:
VERSION_TAG=${{ github.ref_name }}
VERSION=${VERSION_TAG#v}
else
VERSION="dev-${GITHUB_SHA::8}"
VERSION="2.1.0-dev-${GITHUB_SHA::8}" # Default or non-tag build version
fi
echo "VERSION = '$VERSION'" > src/version.py
echo "Version set to $VERSION in src/version.py"
# Use sed to directly update __version__ in __init__.py
sed -i "" -e "s/__version__ = '.*'/__version__ = '$VERSION'/" src/shortcircuit/__init__.py
echo "Version set to $VERSION in src/shortcircuit/__init__.py"

- name: Build Application
run: python build.py
Expand Down Expand Up @@ -102,10 +103,11 @@ jobs:
VERSION_TAG=${{ github.ref_name }}
VERSION=${VERSION_TAG#v}
else
VERSION="dev-${GITHUB_SHA::8}"
VERSION="2.1.0-dev-${GITHUB_SHA::8}" # Default or non-tag build version
fi
echo "VERSION = '$VERSION'" > src/version.py
echo "Version set to $VERSION in src/version.py"
# Use sed to directly update __version__ in __init__.py
sed -i "" -e "s/__version__ = '.*'/__version__ = '$VERSION'/" src/shortcircuit/__init__.py
echo "Version set to $VERSION in src/shortcircuit/__init__.py"

- name: Build Application
run: python build.py
Expand Down Expand Up @@ -144,12 +146,18 @@ jobs:

# Build the AppImage
appimagetool AppDir "ShortCircuit-x86_64.AppImage"

- name: Package (Linux tar.gz)
run: |
tar -czvf "ShortCircuit-Linux-x86_64.tar.gz" -C "dist" "Short Circuit"

- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ShortCircuit-Linux
path: "*.AppImage"
path: |
*.AppImage
*.tar.gz

release:
name: Create GitHub Release
Expand Down
28 changes: 19 additions & 9 deletions src/shortcircuit/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1161,12 +1161,12 @@ def _update_sources_status(self):

if has_errors:
self.status_sources_widget.setText(
f"Sources: {active_count} Active ({total_connections} conn) - ERRORS"
f"Wormhole Sources: {active_count} Active ({total_connections} conn) - ERRORS"
)
self.status_sources_widget.setStyleSheet("color: #e06c75; font-weight: bold;")
else:
self.status_sources_widget.setText(
f"Sources: {active_count} Active ({total_connections} conn)"
f"Wormhole Sources: {active_count} Active ({total_connections} conn)"
)
if active_count > 0:
self.status_sources_widget.setStyleSheet("color: #98c379;")
Expand Down Expand Up @@ -1260,9 +1260,12 @@ def btn_trip_config_clicked(self):
from shortcircuit.model.utility.gui_sources import SourceConfigurationDialog

dialog = SourceConfigurationDialog(self.source_manager, self)
dialog.sources_saved.connect(self._on_sources_saved_in_dialog)
if not dialog.exec():
return

@QtCore.Slot()
def _on_sources_saved_in_dialog(self):
self.nav.setup_mappers()
self.update_auto_refresh_state()
self.on_sources_changed()
Expand Down Expand Up @@ -1296,7 +1299,7 @@ def _start_worker(self):
self.worker_thread.start()
else:
self._update_sources_status()
self._message_box("Map Sources", "Update process is already running.")
self._message_box("Wormhole Sources", "Update process is already running.")

@QtCore.Slot()
def auto_refresh_triggered(self):
Expand Down Expand Up @@ -1415,14 +1418,21 @@ def version_check_done(self, latest):
if ret != QtWidgets.QMessageBox.AcceptRole:
return

QtGui.QDesktopServices.openUrl(
QtCore.QUrl(
"https://github.com/mogglemoss/shortcircuit/releases/tag/{}".format(
latest["tag_name"]
)
)
url_to_open = QtCore.QUrl(
f"https://github.com/mogglemoss/shortcircuit/releases/tag/{latest['tag_name']}"
)

if sys.platform == 'linux':
import subprocess
env = os.environ.copy()
env.pop('LD_LIBRARY_PATH', None)
try:
subprocess.Popen(['xdg-open', url_to_open.toString()], env=env)
except OSError:
webbrowser.open(url_to_open.toString())
else:
QtGui.QDesktopServices.openUrl(url_to_open)

# event: QCloseEvent
def closeEvent(self, event):
self.write_settings()
Expand Down
88 changes: 56 additions & 32 deletions src/shortcircuit/model/utility/gui_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
from shortcircuit.model.evescout_source import EveScoutSource
import uuid


class SourceConfigurationDialog(QtWidgets.QDialog):
def __init__(self, source_manager, parent=None):
super().__init__(parent)
self.source_manager = source_manager
self.setWindowTitle("Map Sources Configuration")
self.setWindowTitle("Wormhole Sources Configuration")
self.sources_saved = QtCore.Signal()
self.setMinimumSize(700, 450)

# Working copy of sources
Expand All @@ -31,7 +33,7 @@ def __init__(self, source_manager, parent=None):
left_widget = QtWidgets.QWidget()
left_layout = QtWidgets.QVBoxLayout(left_widget)
left_layout.setContentsMargins(0, 0, 0, 0)

self.source_list = QtWidgets.QListWidget()
self.source_list.currentRowChanged.connect(self._on_source_selected)
left_layout.addWidget(self.source_list)
Expand All @@ -51,11 +53,13 @@ def __init__(self, source_manager, parent=None):
# Right panel: Configuration form
self.detail_widget = QtWidgets.QStackedWidget()
splitter.addWidget(self.detail_widget)

# Empty page
self.empty_page = QtWidgets.QWidget()
empty_layout = QtWidgets.QVBoxLayout(self.empty_page)
empty_layout.addWidget(QtWidgets.QLabel("Select a source or add a new one."), alignment=QtCore.Qt.AlignCenter)
empty_layout.addWidget(
QtWidgets.QLabel("Select a source or add a new one."), alignment=QtCore.Qt.AlignCenter
)
self.detail_widget.addWidget(self.empty_page)

# Generic Form Page
Expand All @@ -66,9 +70,12 @@ def __init__(self, source_manager, parent=None):
splitter.setSizes([200, 500])

# Bottom buttons
button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Save | QtWidgets.QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box = QtWidgets.QDialogButtonBox(
QtWidgets.QDialogButtonBox.Save | QtWidgets.QDialogButtonBox.Cancel
)
button_box.button(QtWidgets.QDialogButtonBox.Save).clicked.connect(self._save_only)
button_box.rejected.connect(self.reject)
button_box.accepted.connect(super().accept) # Only close on Cancel/X
main_layout.addWidget(button_box)

# Populate list
Expand All @@ -93,7 +100,7 @@ def _on_source_selected(self, row):
# Always save current form state back to model before switching
# (Assuming they switch row after editing, we need real-time data binding.
# Simplest is to bind text changes directly)

src = self.sources[row]
self._build_form(src)
self.detail_widget.setCurrentWidget(self.form_page)
Expand All @@ -103,9 +110,15 @@ def _on_test_connection(self, src):
try:
success, message = src.connect()
if success:
QtWidgets.QMessageBox.information(self, "Connection Test", f"Connection successful!\n\n{message}")
QtWidgets.QMessageBox.information(
self, "Connection Test", f"Connection successful!\n\n{message}"
)
else:
QtWidgets.QMessageBox.warning(self, "Connection Test", f"Connection failed. Please check your settings.\n\nError: {message}")
QtWidgets.QMessageBox.warning(
self,
"Connection Test",
f"Connection failed. Please check your settings.\n\nError: {message}",
)
except Exception as e:
QtWidgets.QMessageBox.critical(self, "Connection Test", f"An error occurred: {str(e)}")
finally:
Expand All @@ -122,72 +135,80 @@ def _build_form(self, src):

# Common fields
self.edit_name = QtWidgets.QLineEdit(src.name)
self.edit_name.textChanged.connect(lambda t: self._update_model_field(src, 'name', t))
self.edit_name.textChanged.connect(lambda t: self._update_model_field(src, "name", t))
self.form_layout.addRow("Name:", self.edit_name)

if src.type == SourceType.TRIPWIRE:
self.edit_url = QtWidgets.QLineEdit(src.url)
self.edit_url.textChanged.connect(lambda t: self._update_model_field(src, 'url', t))
self.edit_url.textChanged.connect(lambda t: self._update_model_field(src, "url", t))
self.form_layout.addRow("URL:", self.edit_url)

self.edit_user = QtWidgets.QLineEdit(src.username)
self.edit_user.textChanged.connect(lambda t: self._update_model_field(src, 'username', t))
self.edit_user.textChanged.connect(
lambda t: self._update_model_field(src, "username", t)
)
self.form_layout.addRow("Username:", self.edit_user)

self.edit_pass = QtWidgets.QLineEdit(src.password)
self.edit_pass.setEchoMode(QtWidgets.QLineEdit.Password)
self.edit_pass.textChanged.connect(lambda t: self._update_model_field(src, 'password', t))
self.edit_pass.textChanged.connect(
lambda t: self._update_model_field(src, "password", t)
)
self.form_layout.addRow("Password:", self.edit_pass)

elif src.type == SourceType.WANDERER:
self.edit_url = QtWidgets.QLineEdit(src.url)
self.edit_url.textChanged.connect(lambda t: self._update_model_field(src, 'url', t))
self.edit_url.textChanged.connect(lambda t: self._update_model_field(src, "url", t))
self.form_layout.addRow("URL:", self.edit_url)

self.edit_map = QtWidgets.QLineEdit(src.map_id)
self.edit_map.textChanged.connect(lambda t: self._update_model_field(src, 'map_id', t))
self.edit_map.textChanged.connect(lambda t: self._update_model_field(src, "map_id", t))
self.form_layout.addRow("Map ID:", self.edit_map)

self.edit_token = QtWidgets.QLineEdit(src.token)
self.edit_token.setEchoMode(QtWidgets.QLineEdit.Password)
self.edit_token.textChanged.connect(lambda t: self._update_model_field(src, 'token', t))
self.edit_token.textChanged.connect(lambda t: self._update_model_field(src, "token", t))
self.form_layout.addRow("Token:", self.edit_token)

elif src.type == SourceType.PATHFINDER:
self.edit_url = QtWidgets.QLineEdit(src.url)
self.edit_url.textChanged.connect(lambda t: self._update_model_field(src, 'url', t))
self.edit_url.textChanged.connect(lambda t: self._update_model_field(src, "url", t))
self.form_layout.addRow("URL:", self.edit_url)

self.edit_token = QtWidgets.QLineEdit(src.token)
self.edit_token.setEchoMode(QtWidgets.QLineEdit.Password)
self.edit_token.textChanged.connect(lambda t: self._update_model_field(src, 'token', t))
self.edit_token.textChanged.connect(lambda t: self._update_model_field(src, "token", t))
self.form_layout.addRow("API Token:", self.edit_token)

lbl_pf_help = QtWidgets.QLabel("Look in: Profile > Settings > API Access")
lbl_pf_help.setStyleSheet("color: #abb2bf; font-style: italic; font-size: 11px;")
self.form_layout.addRow("", lbl_pf_help)

elif src.type == SourceType.EVESCOUT:
lbl_es_help = QtWidgets.QLabel("Eve-Scout provides public Thera connections.")
self.form_layout.addRow("", lbl_es_help)

def _update_model_field(self, src, field, value):
setattr(src, field, value)
# Update list item if name changed
if field == 'name':
if field == "name":
row = self.source_list.currentRow()
if row >= 0:
item = self.source_list.item(row)
item.setText(f"[{src.type.value.capitalize()}] {value}")

def _on_add_source(self):
types = [t.value.capitalize() for t in SourceType]
type_str, ok = QtWidgets.QInputDialog.getItem(self, "Add Source", "Select Source Type:", types, 0, False)
type_str, ok = QtWidgets.QInputDialog.getItem(
self, "Add Source", "Select Source Type:", types, 0, False
)
if ok and type_str:
stype = SourceType(type_str.lower())

# Prevent multiple EveScout sources
if stype == SourceType.EVESCOUT and any(s.type == SourceType.EVESCOUT for s in self.sources):
if stype == SourceType.EVESCOUT and any(
s.type == SourceType.EVESCOUT for s in self.sources
):
QtWidgets.QMessageBox.warning(self, "Warning", "Eve-Scout source already exists.")
return

Expand All @@ -204,12 +225,15 @@ def _on_remove_source(self):
del self.sources[row]
self._populate_list()

def accept(self):
def _save_only(self):
# Apply checkbox states
for i in range(self.source_list.count()):
item = self.source_list.item(i)
self.sources[i].enabled = (item.checkState() == QtCore.Qt.Checked)
self.sources[i].enabled = item.checkState() == QtCore.Qt.Checked

self.source_manager.sources = self.sources
self.source_manager.save_configuration()
self.sources_saved.emit()

def accept(self):
super().accept()
Loading