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
58 changes: 58 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,64 @@ instead of hardcoded values.
hardcoded RGB `QColor` objects to design-system semantic tokens
(`HEALTHY`, `TEXT_SECONDARY`, `WARNING`, `CRITICAL`, `TEXT_MUTED`).

## [Unreleased] — IA Overhaul: COMMAND / FLEET / LAYOUTS / SYSTEM

Six v2.2 tabs collapsed to four IA-aligned tabs that match the operator's
mental model. The Command Center (v3.3 OPS flagship surface) is now the
default home tab, with all live fleet operations under one roof.

### Added
- **Tab containers** under `src/argus_overview/ui/tabs/`:
- `CommandTab` — hosts the flagship `CommandCenterWidget`.
- `FleetTab` — Roster + Intel side-by-side via `QSplitter` (60/40).
- `LayoutsContainer` — Layout presets + Cycle Control via `QSplitter` (70/30).
- `SystemTab` — Settings + Sync via `QSplitter` (60/40).
- **`MainWindowV21._create_tabs()`** — single entry point that builds the
inner widgets, then wraps them in IA containers. The legacy six factory
methods (`_create_main_tab`, `_create_characters_tab`, etc.) remain the
source of truth for cross-tab signal wiring.
- **`MainWindowV21._create_layouts_tab()`** — builds the inner `LayoutsTab`
consumed by the LAYOUTS container, stored as `self.presets_panel`. The
container occupies `self.layouts_tab`.
- **`TestPhase4InformationArchitecture`** + **`tests/test_tab_containers.py`**
— 24 new tests pin the four IA labels, container wiring, and splitter
orientations.
- **IA contract pin** — `_TAB_LABELS` is now `["Command", "Fleet", "Layouts",
"System"]`. `_show_settings` lands on SYSTEM.

### Changed
- **`_show_settings`** — points at the SYSTEM container (which holds
SettingsTab on the left), since "Settings" is no longer a top-level tab.
- **ActionRegistry section comments** — section headers now note the
Phase 4 IA mapping (`OVERVIEW_TOOLBAR → COMMAND`, `ROSTER_TOOLBAR` /
`INTEL_TOOLBAR → FLEET`, `LAYOUTS_TOOLBAR` / `CYCLE_CONTROL_TOOLBAR →
LAYOUTS`, `SYNC_TOOLBAR` / `SETTINGS_PANEL → SYSTEM`). The `PrimaryHome`
enum values are unchanged — actions still bind to the same inner widget.
- **Refresh Layout Groups tooltip** — now says "from the LAYOUTS tab
(Cycle Control pane)" instead of "from Cycle Control tab".

### Tests
- 24 new tests across `tests/test_tab_containers.py` and the new
`TestPhase4InformationArchitecture` class in `tests/test_main_window_v21.py`.
- Full suite: 2,580 passed, 5 skipped.

### Senior review fixes
Addressed 11 findings from the Phase 4 senior review (1 critical):
- **Critical**: `_create_layouts_tab` passed `character_manager` as the
second positional arg to `LayoutsTab` — the actual signature is
`(layout_manager, main_tab, settings_manager=None, character_manager=None)`.
Switched to kwargs, pinned by `test_create_layouts_tab_passes_main_tab_to_main_slot`.
- **Naming symmetry**: inner widget renamed `self.layouts_tab` →
`self.presets_panel` so `self.layouts_tab` consistently denotes the
IA container (matches `command_tab` / `fleet_tab` / `system_tab`).
- **Duplicate signal**: dropped redundant `layouts_tab.layout_applied`
connection; `main_tab.layout_applied` remains the single canonical
source for `_on_layout_applied` and the `CommandIntegrator`.
- **Tautological alias**: removed the `LayoutPresetsPanel` re-export
from `tabs/layouts_tab.py` (and its pinning test). The inner widget
is accessed via `window.presets_panel`; the alias was unconsumed
after the rename.

## [3.2.0] - 2026-04-26 — Intel-Aware Edition

This release ships a 10-PR arc that turns Argus's preview chrome into an
Expand Down
28 changes: 16 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Professional multi-boxing tool for EVE Online on Linux & Windows. Window preview

## Current State

- **Version**: 3.2.0
- **Version**: 3.3.0 (unreleased)
- **Language**: Python
- **Files**: 154 across 2 languages
- **Lines**: 58,394
Expand Down Expand Up @@ -138,7 +138,8 @@ src/argus_overview/
├── ui/ # PySide6 widgets and windows
│ ├── action_registry.py # Single source of truth for all UI actions
│ ├── main_window.py
│ └── tabs/ # Overview, Roster, Layouts, Cycle Control, Sync, Settings
│ └── tabs/ # IA containers (v3.3 OPS): command_tab, fleet_tab,
│ # layouts_tab (container), system_tab
├── core/ # Business logic
├── platform/ # Cross-platform abstraction layer
│ ├── base.py # Abstract base classes
Expand Down Expand Up @@ -166,16 +167,19 @@ All UI actions follow tier rules:
4. Bind handler in appropriate widget
5. Run audit: `python -m argus_overview.ui.action_registry`

### Tab Structure
### Tab Structure (v3.3 OPS — Phase 4 IA)

| Tab | Purpose | Toolbar |
|-----|---------|---------|
| Overview | Window preview, capture | OVERVIEW_TOOLBAR |
| Roster | Characters & teams | ROSTER_TOOLBAR |
| Layouts | Window arrangement patterns | LAYOUTS_TOOLBAR |
| Cycle Control | Hotkeys, cycling | CYCLE_CONTROL_TOOLBAR |
| Sync | EVE settings sync | SYNC_TOOLBAR |
| Settings | App configuration | SETTINGS_PANEL |
| Tab | Container | Inner widgets | Toolbar homes covered |
|-----|-----------|---------------|------------------------|
| Command | `CommandTab` | `CommandCenterWidget` (live operations) | OVERVIEW_TOOLBAR |
| Fleet | `FleetTab` (60/40 splitter) | `CharactersTeamsTab` + `IntelTab` | ROSTER_TOOLBAR, INTEL_TOOLBAR |
| Layouts | `LayoutsContainer` (70/30 splitter) | `LayoutsTab` + `HotkeysTab` | LAYOUTS_TOOLBAR, CYCLE_CONTROL_TOOLBAR |
| System | `SystemTab` (60/40 splitter) | `SettingsTab` + `SettingsSyncTab` | SETTINGS_PANEL, SYNC_TOOLBAR |

The six v2.2 tabs (Overview, Roster, Cycle Control, Intel, Sync, Settings)
are still built as inner widgets so cross-tab signal wiring and the
`ActionRegistry` primary homes remain stable — they're just composed into
the four IA containers above. `_show_settings` lands on the SYSTEM tab.

### Platform Abstraction
- PySide6 signal/slot architecture
Expand Down Expand Up @@ -207,7 +211,7 @@ This is a fan project, not affiliated with or endorsed by CCP hf.

## Testing

- **2,184 tests** via pytest
- **2,580 tests** via pytest
- Python 3.10, 3.11, 3.12 matrix
- Platform-specific tests guarded by `sys.platform` checks
- Run: `pytest tests/ -v` or `pytest tests/ -v --cov=src/argus_overview`
Expand Down
20 changes: 11 additions & 9 deletions DEV_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,17 @@ but must not create duplicate clickable UI elements.
3. **Register in ActionRegistry**: Edit `ui/action_registry.py`

```python
self.register(ActionSpec(
id="my_new_action",
label="My Action Label",
scope=ActionScope.TAB, # or GLOBAL, OBJECT
primary_home=PrimaryHome.OVERVIEW_TOOLBAR, # canonical location
tooltip="Description of action",
shortcut="<ctrl>+<shift>+a", # optional
handler_name="_my_action_handler",
))
self.register(
ActionSpec(
id="my_new_action",
label="My Action Label",
scope=ActionScope.TAB, # or GLOBAL, OBJECT
primary_home=PrimaryHome.OVERVIEW_TOOLBAR, # canonical location
tooltip="Description of action",
shortcut="<ctrl>+<shift>+a", # optional
handler_name="_my_action_handler",
)
)
```

4. **Connect handler**: In the appropriate widget/tab, bind the handler:
Expand Down
10 changes: 6 additions & 4 deletions PACKAGE_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ from eve_overview_pro.core.layout_manager import LayoutManager, GridPattern
manager = LayoutManager()

# Calculate grid layout
screen = {'x': 0, 'y': 0, 'width': 1920, 'height': 1080}
windows = ['0x123', '0x124', '0x125', '0x126']
screen = {"x": 0, "y": 0, "width": 1920, "height": 1080}
windows = ["0x123", "0x124", "0x125", "0x126"]
layout = manager.calculate_grid_layout(GridPattern.GRID_2X2, windows, screen)
```

Expand All @@ -168,11 +168,13 @@ from eve_overview_pro.core.alert_detector import AlertDetector, AlertLevel

detector = AlertDetector()


def on_alert(level):
print(f"ALERT: {level}")

detector.register_callback('0x123', on_alert)
alert_level = detector.analyze_frame('0x123', image)

detector.register_callback("0x123", on_alert)
alert_level = detector.analyze_frame("0x123", image)
```

### Settings Sync
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
> ---
>

# Argus Overview v3.2.0
# Argus Overview v3.3.0

**The Complete Professional Multi-Boxing Solution for EVE Online**

Expand Down
58 changes: 29 additions & 29 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ Information about a window.
```python
@dataclass
class WindowInfo:
window_id: str # Platform-specific window identifier
title: str # Window title
class_name: str # Window class (default: "")
window_id: str # Platform-specific window identifier
title: str # Window title
class_name: str # Window class (default: "")
```

#### `ScreenGeometry`
Expand All @@ -79,11 +79,11 @@ Screen/monitor geometry information.
```python
@dataclass
class ScreenGeometry:
x: int # X position
y: int # Y position
width: int # Screen width in pixels
height: int # Screen height in pixels
is_primary: bool # True if primary display (default: False)
x: int # X position
y: int # Y position
width: int # Screen width in pixels
height: int # Screen height in pixels
is_primary: bool # True if primary display (default: False)
```

---
Expand Down Expand Up @@ -309,11 +309,11 @@ Threat level classification for intel reports.

```python
class ThreatLevel(Enum):
CLEAR = "clear" # System reported clear
INFO = "info" # General intel, not immediate threat
WARNING = "warning" # Hostiles nearby (2+ jumps)
DANGER = "danger" # Hostiles close (1 jump) or small gang
CRITICAL = "critical" # Hostiles in system or capital ships
CLEAR = "clear" # System reported clear
INFO = "info" # General intel, not immediate threat
WARNING = "warning" # Hostiles nearby (2+ jumps)
DANGER = "danger" # Hostiles close (1 jump) or small gang
CRITICAL = "critical" # Hostiles in system or capital ships
```

---
Expand All @@ -325,15 +325,15 @@ Represents parsed intel from a chat message.
```python
@dataclass
class IntelReport:
system: Optional[str] # EVE system name (e.g., "HED-GP")
threat_level: ThreatLevel # Assessed threat level
hostile_count: Optional[int] # Number of hostiles if known
ship_types: List[str] # Detected ship types
player_names: List[str] # Detected player names
raw_message: str # Original message text
timestamp: datetime # Message timestamp
channel: str # Source channel name
reporter: str # Player who sent the message
system: Optional[str] # EVE system name (e.g., "HED-GP")
threat_level: ThreatLevel # Assessed threat level
hostile_count: Optional[int] # Number of hostiles if known
ship_types: List[str] # Detected ship types
player_names: List[str] # Detected player names
raw_message: str # Original message text
timestamp: datetime # Message timestamp
channel: str # Source channel name
reporter: str # Player who sent the message
jumps_from_current: Optional[int] # Distance from current system
```

Expand Down Expand Up @@ -381,9 +381,9 @@ Types of alerts that can be triggered.

```python
class AlertType(Enum):
VISUAL_BORDER = "border" # Flash window border
VISUAL_OVERLAY = "overlay" # Show overlay on preview
AUDIO = "audio" # Play sound
VISUAL_BORDER = "border" # Flash window border
VISUAL_OVERLAY = "overlay" # Show overlay on preview
AUDIO = "audio" # Play sound
SYSTEM_NOTIFICATION = "notification" # Desktop notification
```

Expand All @@ -405,7 +405,7 @@ class AlertConfig:

# Thresholds
min_threat_level: str = "warning" # Minimum level to alert on
jumps_threshold: int = 5 # Only alert if within N jumps
jumps_threshold: int = 5 # Only alert if within N jumps

# Visual settings
border_color: str = "#FF0000"
Expand Down Expand Up @@ -438,9 +438,9 @@ dispatcher.alert_triggered.connect(my_handler)
#### Signals

```python
border_flash_requested = Signal(str, int) # (color, duration_ms)
overlay_requested = Signal(object) # (IntelReport)
alert_triggered = Signal(object, object) # (IntelReport, AlertType)
border_flash_requested = Signal(str, int) # (color, duration_ms)
overlay_requested = Signal(object) # (IntelReport)
alert_triggered = Signal(object, object) # (IntelReport, AlertType)
```

#### `__init__(config: Optional[AlertConfig] = None, parent: Optional[QObject] = None)`
Expand Down
3 changes: 2 additions & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,8 @@ All subprocess calls validate window IDs to prevent command injection:

```python
# Window ID validation regex
WINDOW_ID_PATTERN = re.compile(r'^0x[0-9a-fA-F]+$')
WINDOW_ID_PATTERN = re.compile(r"^0x[0-9a-fA-F]+$")


def validate_window_id(window_id: str) -> bool:
"""Validate window ID format before subprocess calls."""
Expand Down
4 changes: 2 additions & 2 deletions docs/SMOKE_TEST_v3.2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ from datetime import datetime

# In MainWindowV21 instance scope (e.g., self):
report = IntelReport(
system="HED-GP", # change to test specific systems
threat_level=ThreatLevel.DANGER, # CLEAR / INFO / WARNING / DANGER / CRITICAL
system="HED-GP", # change to test specific systems
threat_level=ThreatLevel.DANGER, # CLEAR / INFO / WARNING / DANGER / CRITICAL
hostile_count=3,
ship_types=["sabre", "broadsword"],
player_names=[],
Expand Down
Binary file added docs/screenshots/command-center-palette-v33.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/command-center-v33.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/command-tab-v33.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/fleet-tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/layouts-tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/system-tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading