Skip to content

Commit

Permalink
GUI variable interaction
Browse files Browse the repository at this point in the history
  • Loading branch information
lane-neuro committed Jun 24, 2024
1 parent 4392802 commit b8c08ac
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,72 +1,46 @@
"""
DataCollectionDialog
This module defines the DataCollectionDialog class, which is responsible for managing the Data Collection tools and
their GUI representation within the research analytics suite. It handles the initialization and updates the GUI
accordingly.
Author: Lane
Copyright: Lane
Credits: Lane
License: BSD 3-Clause License
Version: 0.0.0.1
Maintainer: Lane
Email: justlane@uw.edu
Status: Prototype
"""

import dearpygui.dearpygui as dpg
from research_analytics_suite.utils.CustomLogger import CustomLogger

from research_analytics_suite.gui.modules.PrimaryView import PrimaryView
from research_analytics_suite.utils import CustomLogger


class DataCollectionDialog:
"""A class to manage Data Collection tools and their GUI representation."""

def __init__(self, width: int, height: int):
"""
Initializes the DataCollectionDialog with the given width and height.
Args:
width (int): The width of the dialog.
height (int): The height of the dialog.
"""
self.width = width
self.height = height
self.primary_view = None
self._logger = CustomLogger()

def draw(self, parent):
"""Draws the GUI elements for the Data Collection section."""
with dpg.group(parent=parent):
dpg.add_text("Data Collection Tools", parent=parent)

with dpg.group(horizontal=True):
dpg.add_button(label="Data Sources", callback=self.show_data_sources)
dpg.add_button(label="Data Import", callback=self.show_data_import)
dpg.add_button(label="Surveys/Forms", callback=self.show_surveys_forms)
dpg.add_button(label="Sensor Integration", callback=self.show_sensor_integration)
dpg.add_button(label="Manual Entry", callback=self.show_manual_entry)
dpg.add_button(label="Data Quality Checks", callback=self.show_data_quality_checks)
async def draw(self, parent):
with dpg.group(parent=parent, tag="data_collection_tools_group"):
dpg.add_text("Data Collection Tools")
await self.show_memory_collections()

def show_data_sources(self, sender, app_data, user_data):
"""Displays the Data Sources section."""
self._logger.info("Data Sources clicked")
async def show_memory_collections(self):
with dpg.group(label="Memory Collections", tag="memory_collections_group",
parent="data_collection_tools_group", width=-1, height=-1):
self.primary_view = PrimaryView(parent="memory_collections_group")
await self.primary_view.initialize_dialog()

def show_data_import(self, sender, app_data, user_data):
"""Displays the Data Import section."""
self._logger.info("Data Import clicked")

def show_surveys_forms(self, sender, app_data, user_data):
"""Displays the Surveys/Forms section."""
self._logger.info("Surveys/Forms clicked")

def show_sensor_integration(self, sender, app_data, user_data):
"""Displays the Sensor Integration section."""
self._logger.info("Sensor Integration clicked")

def show_manual_entry(self, sender, app_data, user_data):
"""Displays the Manual Entry section."""
self._logger.info("Manual Entry clicked")

def show_data_quality_checks(self, sender, app_data, user_data):
"""Displays the Data Quality Checks section."""
self._logger.info("Data Quality Checks clicked")

def show_advanced_view(self, slot):
"""Displays the Advanced Slot View for a given slot."""
from research_analytics_suite.gui import AdvancedSlotView
advanced_view = AdvancedSlotView(parent="data_sources_window", slot=slot)
advanced_view.draw()
2 changes: 2 additions & 0 deletions research_analytics_suite/gui/launcher/GuiLauncher.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,5 +232,7 @@ async def setup_planning_pane(self) -> None:
async def setup_data_collection_pane(self) -> None:
"""Sets up the data collection pane asynchronously."""
with dpg.group(parent="data_collection_pane"):
self.data_collection_dialog = DataCollectionDialog(width=800, height=600)
dpg.add_text("Data Collection Tools")
await self.data_collection_dialog.show_memory_collections()

83 changes: 83 additions & 0 deletions research_analytics_suite/gui/modules/AdvancedSlotView.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
AdvancedSlotView Module
This module defines the AdvancedSlotView class, which is responsible for managing the detailed GUI representation of individual slots.
"""
import dearpygui.dearpygui as dpg
from research_analytics_suite.data_engine.memory.MemorySlot import MemorySlot


class AdvancedSlotView:
"""A class to manage the detailed GUI representation of individual slots."""

def __init__(self, parent, slot: MemorySlot):
"""
Initializes the AdvancedSlotView with the given slot.
Args:
parent (str): The parent GUI element ID.
slot (MemorySlot): The memory slot to represent.
"""
self.parent = parent
self.slot = slot
self.slot_group_tag = f"advanced_slot_group_{slot.memory_id}"
self.draw()

def draw(self):
"""Draws the advanced slot view elements."""
with dpg.group(tag=self.slot_group_tag, parent=self.parent):
dpg.add_text(f"Slot: {self.slot.name}", parent=self.slot_group_tag)
dpg.add_text(f"Memory ID: {self.slot.memory_id}", parent=self.slot_group_tag)

# Key-Value pairs
for key, value in self.slot.data.items():
dpg.add_input_text(label=f"{key}", default_value=str(value), parent=self.slot_group_tag)

# Metadata
dpg.add_text("Metadata", parent=self.slot_group_tag)
for key, value in self.slot.metadata.items():
dpg.add_text(f"{key}: {value}", parent=self.slot_group_tag)

# Operation required switch
dpg.add_checkbox(label="Operation Required", default_value=self.slot.operation_required,
parent=self.slot_group_tag)

# Save and Cancel buttons
dpg.add_button(label="Save", callback=self.save, parent=self.slot_group_tag)
dpg.add_button(label="Cancel", callback=self.cancel, parent=self.slot_group_tag)

# Export functionality
with dpg.group(horizontal=True, parent=self.slot_group_tag):
dpg.add_button(label="Export as CSV", callback=self.export_csv)
dpg.add_button(label="Export as JSON", callback=self.export_json)

def update(self, slot: MemorySlot):
"""Updates the advanced slot view elements."""
self.slot = slot
if dpg.does_item_exist(self.slot_group_tag):
dpg.delete_item(self.slot_group_tag)
self.draw()

def remove(self):
"""Removes the advanced slot view elements from the GUI."""
if dpg.does_item_exist(self.slot_group_tag):
dpg.delete_item(self.slot_group_tag)

def save(self):
"""Callback function for saving changes."""
# Logic to save changes to the slot
pass

def cancel(self):
"""Callback function for canceling changes."""
self.remove()

def export_csv(self):
"""Callback function for exporting slot data as CSV."""
# Logic to export slot data as CSV
pass

def export_json(self):
"""Callback function for exporting slot data as JSON."""
# Logic to export slot data as JSON
pass
55 changes: 55 additions & 0 deletions research_analytics_suite/gui/modules/CollectionSummaryView.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
CollectionSummaryView Module
This module defines the CollectionSummaryView class, which is responsible for managing the GUI representation of collections and their slots.
"""
import dearpygui.dearpygui as dpg
from research_analytics_suite.data_engine.memory.MemorySlotCollection import MemorySlotCollection


class CollectionSummaryView:
"""A class to manage the GUI representation of collections and their slots."""

def __init__(self, parent, collection_list: list[MemorySlotCollection]):
"""
Initializes the CollectionSummaryView with the given collections.
Args:
parent (str): The parent GUI element ID.
collection_list (list[MemorySlotCollection]): The list of memory slot collections to represent.
"""
self.parent = parent
self.collection_list = collection_list
self.collection_groups = {}
self.draw()

def draw(self):
"""Draws the collection summary view elements."""
for collection in self.collection_list:
collection_tag = f"collection_group_{collection.collection_id}"
self.collection_groups[collection.collection_id] = collection_tag

with dpg.group(tag=collection_tag, parent=self.parent, horizontal=True):
dpg.add_text(f"Collection: {collection.name}", parent=collection_tag)
for slot in collection.slots:
from research_analytics_suite.gui import SlotPreview
slot_preview = SlotPreview(parent=collection_tag, slot=slot, width=200, height=100)
slot_preview.draw()

def update(self, collections: list[MemorySlotCollection]):
"""Updates the collection summary view elements."""
self.collection_list = collections
for collection_tag in self.collection_groups.values():
if dpg.does_item_exist(collection_tag):
dpg.delete_item(collection_tag)
self.draw()

def add_collection(self, collection: MemorySlotCollection):
"""Adds a new collection to the view."""
self.collection_list.append(collection)
self.update(self.collection_list)

def remove_collection(self, collection_id: str):
"""Removes a collection from the view."""
self.collection_list = [c for c in self.collection_list if c.collection_id != collection_id]
self.update(self.collection_list)
90 changes: 90 additions & 0 deletions research_analytics_suite/gui/modules/PrimaryView.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
PrimaryView Module
This module defines the PrimaryView class, which is responsible for managing the main GUI window and its components.
"""
import asyncio
from typing import Optional, Any

import dearpygui.dearpygui as dpg
from research_analytics_suite.data_engine.memory.MemorySlotCollection import MemorySlotCollection
from research_analytics_suite.gui.modules.CollectionSummaryView import CollectionSummaryView
from research_analytics_suite.operation_manager import BaseOperation
from research_analytics_suite.utils import CustomLogger


class PrimaryView:
"""A class to manage the main GUI window and its components."""

def __init__(self, parent=None):
"""Initializes the PrimaryView."""

from research_analytics_suite.operation_manager import OperationControl
self.operation_control = OperationControl()

self._logger = CustomLogger()

from research_analytics_suite.data_engine import MemoryManager
self._memory_manager = MemoryManager()

self.collections = []
self.search_bar = None
self.notification_area = None
self.collection_summary = None
self.advanced_slot_view = None
self.update_operation = None
self.parent = parent

async def initialize_dialog(self) -> None:
"""Initializes the user interface."""
with dpg.window(label="Primary Window", tag="primary_view", parent=self.parent, width=-1, height=-1):
self.search_bar = dpg.add_input_text(label="Search", callback=self.search)
self.notification_area = dpg.add_text("Notifications will appear here.")

from research_analytics_suite.gui.modules.CollectionSummaryView import CollectionSummaryView
self.collection_summary = CollectionSummaryView(parent="primary_view", collection_list=self.collections)
self.collection_summary.draw()

self.advanced_slot_view = None

self.update_operation = await self.add_update_operation()

async def add_update_operation(self) -> Optional[Any]:
try:
operation = await self.operation_control.operation_manager.add_operation_with_parameters(
operation_type=BaseOperation, name="gui_DataCollectionUpdateTask",
action=self.update_collections, persistent=True, concurrent=True)
operation.is_ready = True
return operation
except Exception as e:
self._logger.error(e, self)
return None

def search(self, sender, data):
"""Callback function for search bar."""
search_query = dpg.get_value(self.search_bar)
# Logic for searching collections and slots based on the query

def add_collection(self, collection: MemorySlotCollection):
"""Adds a new collection to the primary view."""
self.collections.append(collection)
self.collection_summary.add_collection(collection)

def remove_collection(self, collection_id: str):
"""Removes a collection from the primary view."""
self.collections = [c for c in self.collections if c.collection_id != collection_id]
self.collection_summary.remove_collection(collection_id)

def show_advanced_slot_view(self, slot):
"""Displays the advanced slot view for a given slot."""
if dpg.does_item_exist("advanced_slot_window"):
dpg.delete_item("advanced_slot_window")
with dpg.window(label="Advanced Slot View", tag="advanced_slot_window", width=500, height=500):
from research_analytics_suite.gui import AdvancedSlotView
self.advanced_slot_view = AdvancedSlotView(parent="advanced_slot_group", slot=slot)

async def update_collections(self):
"""Updates the primary view with the given collections."""
self.collections = await self._memory_manager.list_collections()
self.collection_summary.update(self.collections)
await asyncio.sleep(0.1)
62 changes: 62 additions & 0 deletions research_analytics_suite/gui/modules/SlotPreview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""
SlotPreview Module
This module defines the SlotPreview class, which is responsible for managing the GUI representation of individual slots.
"""
import uuid
import dearpygui.dearpygui as dpg
from research_analytics_suite.data_engine.memory.MemorySlot import MemorySlot


class SlotPreview:
"""A class to manage the GUI representation of individual slots."""

def __init__(self, parent, slot: MemorySlot, width: int, height: int):
"""
Initializes the SlotPreview with the given slot.
Args:
parent (str): The parent GUI element ID.
slot (MemorySlot): The memory slot to represent.
width (int): The width of the slot preview.
height (int): The height of the slot preview.
"""
self._runtime_id = f"{uuid.uuid4().hex[:6]}"

self.parent = parent
self.slot = slot
self.width = width
self.height = height

self.slot_group_tag = f"slot_group_{slot.memory_id}"

def draw(self):
"""Draws the slot preview elements."""
with dpg.group(tag=self.slot_group_tag, parent=self.parent, horizontal=True):
# Slot name
dpg.add_text(f"Slot: {self.slot.name}", parent=self.slot_group_tag)

# Key-Value pairs preview
for key, value in self.slot.data.items():
dpg.add_text(f"{key}: {value}", parent=self.slot_group_tag)

# Operation required indicator
operation_status = "Yes" if self.slot.operation_required else "No"
dpg.add_text(f"Operation Required: {operation_status}", parent=self.slot_group_tag)

def update(self, slot: MemorySlot):
"""Updates the slot preview elements."""
self.slot = slot
if dpg.does_item_exist(self.slot_group_tag):
dpg.delete_item(self.slot_group_tag)
self.draw()

def remove(self):
"""Removes the slot preview elements from the GUI."""
if dpg.does_item_exist(self.slot_group_tag):
dpg.delete_item(self.slot_group_tag)

@property
def runtime_id(self) -> str:
"""Get the runtime ID of the slot preview."""
return self._runtime_id
Loading

0 comments on commit b8c08ac

Please sign in to comment.