CoolFace
Apppublic

lattmamb/aether-rides

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
ui_components.py754 linesDownload Raw Back to root
1"""2Frontend UI components for Vision OS3"""4 5import os6import sys7import logging8from typing import Dict, List, Any, Optional, Callable9from PyQt5.QtWidgets import (10    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 11    QPushButton, QLabel, QLineEdit, QTextEdit, QScrollArea, 12    QFrame, QSplitter, QTabWidget, QComboBox, QCheckBox, QFileDialog,13    QListWidget, QListWidgetItem, QProgressBar, QMenu, QAction, QSystemTrayIcon14)15from PyQt5.QtGui import (16    QIcon, QPixmap, QFont, QColor, QPalette, QLinearGradient, 17    QGradient, QBrush, QPainter, QPen, QRadialGradient, QFontMetrics18)19from PyQt5.QtCore import (20    Qt, QSize, QPoint, QRect, QPropertyAnimation, QEasingCurve, 21    QTimer, QThread, pyqtSignal, pyqtSlot, QUrl, QObject22)23 24logger = logging.getLogger("vision_os.frontend")25 26# Define color scheme based on the reference images27class ColorScheme:28    """Color scheme for Vision OS UI based on reference images"""29    30    # Background colors31    BACKGROUND_DARK = "#0B0B0F"  # Deep black background32    BACKGROUND_PANEL = "#141821"  # Slightly lighter panel background33    34    # Accent colors35    ACCENT_BLUE = "#00E0FF"      # Neon blue36    ACCENT_CYAN = "#35F2DB"      # Cyan accent37    ACCENT_PURPLE = "#9D4EDD"    # Purple accent38    39    # Gradient colors40    GRADIENT_START = "#1E2432"   # Dark blue for gradients41    GRADIENT_END = "#0F131C"     # Darker blue for gradients42    43    # Text colors44    TEXT_PRIMARY = "#FFFFFF"     # White text45    TEXT_SECONDARY = "#B0B7C3"   # Light gray text46    47    # Status colors48    STATUS_SUCCESS = "#4CAF50"   # Green for success49    STATUS_WARNING = "#FFC107"   # Yellow for warnings50    STATUS_ERROR = "#F44336"     # Red for errors51    52    @staticmethod53    def get_background_gradient():54        """Create a background gradient"""55        gradient = QLinearGradient(0, 0, 0, 1000)56        gradient.setColorAt(0, QColor(ColorScheme.GRADIENT_START))57        gradient.setColorAt(1, QColor(ColorScheme.GRADIENT_END))58        return gradient59    60    @staticmethod61    def get_accent_gradient():62        """Create an accent gradient"""63        gradient = QLinearGradient(0, 0, 400, 0)64        gradient.setColorAt(0, QColor(ColorScheme.ACCENT_BLUE))65        gradient.setColorAt(1, QColor(ColorScheme.ACCENT_PURPLE))66        return gradient67 68 69class StyleSheet:70    """StyleSheet for Vision OS UI"""71    72    @staticmethod73    def get_base_stylesheet():74        """Get the base stylesheet for the application"""75        return f"""76        QWidget {{77            background-color: {ColorScheme.BACKGROUND_DARK};78            color: {ColorScheme.TEXT_PRIMARY};79            font-family: 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif;80            font-size: 14px;81        }}82        83        QMainWindow {{84            background-color: {ColorScheme.BACKGROUND_DARK};85        }}86        87        QLabel {{88            color: {ColorScheme.TEXT_PRIMARY};89        }}90        91        QLabel#title {{92            font-size: 24px;93            font-weight: bold;94            color: {ColorScheme.ACCENT_BLUE};95        }}96        97        QLabel#subtitle {{98            font-size: 16px;99            color: {ColorScheme.TEXT_SECONDARY};100        }}101        102        QPushButton {{103            background-color: {ColorScheme.BACKGROUND_PANEL};104            color: {ColorScheme.ACCENT_BLUE};105            border: 1px solid {ColorScheme.ACCENT_BLUE};106            border-radius: 8px;107            padding: 8px 16px;108            font-weight: bold;109        }}110        111        QPushButton:hover {{112            background-color: rgba(0, 224, 255, 0.2);113        }}114        115        QPushButton:pressed {{116            background-color: rgba(0, 224, 255, 0.3);117        }}118        119        QLineEdit, QTextEdit {{120            background-color: {ColorScheme.BACKGROUND_PANEL};121            color: {ColorScheme.TEXT_PRIMARY};122            border: 1px solid #2A2F3C;123            border-radius: 8px;124            padding: 8px;125        }}126        127        QLineEdit:focus, QTextEdit:focus {{128            border: 1px solid {ColorScheme.ACCENT_BLUE};129        }}130        131        QScrollArea, QListWidget {{132            background-color: {ColorScheme.BACKGROUND_PANEL};133            border: 1px solid #2A2F3C;134            border-radius: 8px;135        }}136        137        QTabWidget::pane {{138            background-color: {ColorScheme.BACKGROUND_PANEL};139            border: 1px solid #2A2F3C;140            border-radius: 8px;141        }}142        143        QTabBar::tab {{144            background-color: {ColorScheme.BACKGROUND_DARK};145            color: {ColorScheme.TEXT_SECONDARY};146            border: 1px solid #2A2F3C;147            border-bottom: none;148            border-top-left-radius: 8px;149            border-top-right-radius: 8px;150            padding: 8px 16px;151            margin-right: 2px;152        }}153        154        QTabBar::tab:selected {{155            background-color: {ColorScheme.BACKGROUND_PANEL};156            color: {ColorScheme.ACCENT_BLUE};157            border-bottom: none;158        }}159        160        QComboBox {{161            background-color: {ColorScheme.BACKGROUND_PANEL};162            color: {ColorScheme.TEXT_PRIMARY};163            border: 1px solid #2A2F3C;164            border-radius: 8px;165            padding: 8px;166        }}167        168        QComboBox::drop-down {{169            border: none;170        }}171        172        QComboBox QAbstractItemView {{173            background-color: {ColorScheme.BACKGROUND_PANEL};174            color: {ColorScheme.TEXT_PRIMARY};175            selection-background-color: rgba(0, 224, 255, 0.2);176        }}177        178        QProgressBar {{179            background-color: {ColorScheme.BACKGROUND_PANEL};180            color: {ColorScheme.TEXT_PRIMARY};181            border: 1px solid #2A2F3C;182            border-radius: 8px;183            text-align: center;184        }}185        186        QProgressBar::chunk {{187            background-color: {ColorScheme.ACCENT_BLUE};188            border-radius: 8px;189        }}190        191        QCheckBox {{192            color: {ColorScheme.TEXT_PRIMARY};193        }}194        195        QCheckBox::indicator {{196            width: 18px;197            height: 18px;198            border: 1px solid #2A2F3C;199            border-radius: 4px;200        }}201        202        QCheckBox::indicator:checked {{203            background-color: {ColorScheme.ACCENT_BLUE};204        }}205        """206 207 208class NeomorphicButton(QPushButton):209    """Custom button with neomorphic design"""210    211    def __init__(self, text="", parent=None):212        super().__init__(text, parent)213        self.setFixedHeight(50)214        self.setMinimumWidth(120)215        self.setCursor(Qt.PointingHandCursor)216        217        # Set up shadow effect218        self.setStyleSheet("""219            NeomorphicButton {220                background-color: #141821;221                color: #00E0FF;222                border: none;223                border-radius: 10px;224                font-weight: bold;225                padding: 10px 20px;226                text-align: center;227            }228        """)229    230    def paintEvent(self, event):231        painter = QPainter(self)232        painter.setRenderHint(QPainter.Antialiasing)233        234        # Draw button background235        rect = self.rect()236        painter.setPen(Qt.NoPen)237        238        # Create gradient background239        gradient = QLinearGradient(0, 0, 0, rect.height())240        gradient.setColorAt(0, QColor("#1E2432"))241        gradient.setColorAt(1, QColor("#0F131C"))242        painter.setBrush(QBrush(gradient))243        244        # Draw rounded rectangle245        painter.drawRoundedRect(rect, 10, 10)246        247        # Draw top-left shadow (lighter)248        painter.setPen(QPen(QColor(255, 255, 255, 20), 1))249        painter.drawLine(rect.left() + 5, rect.top() + 5, rect.right() - 5, rect.top() + 5)250        painter.drawLine(rect.left() + 5, rect.top() + 5, rect.left() + 5, rect.bottom() - 5)251        252        # Draw bottom-right shadow (darker)253        painter.setPen(QPen(QColor(0, 0, 0, 60), 1))254        painter.drawLine(rect.left() + 5, rect.bottom() - 5, rect.right() - 5, rect.bottom() - 5)255        painter.drawLine(rect.right() - 5, rect.top() + 5, rect.right() - 5, rect.bottom() - 5)256        257        # Draw text258        painter.setPen(QColor(ColorScheme.ACCENT_BLUE))259        painter.setFont(self.font())260        painter.drawText(rect, Qt.AlignCenter, self.text())261 262 263class GlassmorphicPanel(QFrame):264    """Custom panel with glassmorphic design"""265    266    def __init__(self, parent=None):267        super().__init__(parent)268        self.setObjectName("glassmorphicPanel")269        self.setStyleSheet("""270            #glassmorphicPanel {271                background-color: rgba(30, 36, 50, 0.7);272                border: 1px solid rgba(255, 255, 255, 0.1);273                border-radius: 16px;274            }275        """)276        277        # Set up layout278        self.layout = QVBoxLayout(self)279        self.layout.setContentsMargins(20, 20, 20, 20)280        self.layout.setSpacing(15)281        self.setLayout(self.layout)282 283 284class ParticleBackground(QWidget):285    """Background widget with particle effect"""286    287    def __init__(self, parent=None):288        super().__init__(parent)289        self.setAttribute(Qt.WA_StyledBackground, True)290        self.setStyleSheet(f"background-color: {ColorScheme.BACKGROUND_DARK};")291        292        # Particle properties293        self.particles = []294        self.num_particles = 100295        self.init_particles()296        297        # Animation timer298        self.timer = QTimer(self)299        self.timer.timeout.connect(self.update_particles)300        self.timer.start(50)  # Update every 50ms301    302    def init_particles(self):303        """Initialize particles"""304        import random305        306        for _ in range(self.num_particles):307            particle = {308                'x': random.randint(0, self.width() or 800),309                'y': random.randint(0, self.height() or 600),310                'size': random.uniform(1, 3),311                'speed': random.uniform(0.2, 1.0),312                'opacity': random.uniform(0.1, 0.5),313                'color': random.choice([314                    QColor(ColorScheme.ACCENT_BLUE),315                    QColor(ColorScheme.ACCENT_CYAN),316                    QColor(ColorScheme.ACCENT_PURPLE)317                ])318            }319            self.particles.append(particle)320    321    def update_particles(self):322        """Update particle positions"""323        import random324        325        for particle in self.particles:326            # Move particles upward with slight horizontal drift327            particle['y'] -= particle['speed']328            particle['x'] += random.uniform(-0.5, 0.5)329            330            # Reset particles that go off-screen331            if particle['y'] < -10:332                particle['y'] = self.height() + 10333                particle['x'] = random.randint(0, self.width())334        335        self.update()  # Trigger repaint336    337    def paintEvent(self, event):338        """Paint the particles"""339        super().paintEvent(event)340        341        painter = QPainter(self)342        painter.setRenderHint(QPainter.Antialiasing)343        344        # Draw particles345        for particle in self.particles:346            color = particle['color']347            color.setAlphaF(particle['opacity'])348            painter.setPen(Qt.NoPen)349            painter.setBrush(color)350            351            painter.drawEllipse(352                QPoint(int(particle['x']), int(particle['y'])),353                particle['size'],354                particle['size']355            )356    357    def resizeEvent(self, event):358        """Handle resize events"""359        super().resizeEvent(event)360        361        # Adjust particle positions for new size362        import random363        for particle in self.particles:364            particle['x'] = random.randint(0, self.width())365            particle['y'] = random.randint(0, self.height())366 367 368class ChatPanel(QWidget):369    """Chat interface panel for interacting with Vision OS"""370    371    def __init__(self, parent=None, message_callback=None):372        super().__init__(parent)373        self.message_callback = message_callback374        self.setup_ui()375    376    def setup_ui(self):377        """Set up the chat panel UI"""378        layout = QVBoxLayout(self)379        layout.setContentsMargins(0, 0, 0, 0)380        381        # Chat history area382        self.chat_history = QTextEdit()383        self.chat_history.setReadOnly(True)384        self.chat_history.setStyleSheet("""385            QTextEdit {386                background-color: rgba(20, 24, 33, 0.7);387                border: 1px solid rgba(255, 255, 255, 0.1);388                border-radius: 12px;389                padding: 15px;390                font-size: 14px;391            }392        """)393        394        # Input area395        input_container = QWidget()396        input_layout = QHBoxLayout(input_container)397        input_layout.setContentsMargins(0, 10, 0, 0)398        399        self.message_input = QTextEdit()400        self.message_input.setPlaceholderText("Type your message here...")401        self.message_input.setMaximumHeight(80)402        self.message_input.setStyleSheet("""403            QTextEdit {404                background-color: rgba(20, 24, 33, 0.8);405                border: 1px solid rgba(255, 255, 255, 0.1);406                border-radius: 12px;407                padding: 10px 15px;408                font-size: 14px;409            }410        """)411        412        self.send_button = NeomorphicButton("Send")413        self.send_button.setFixedSize(100, 40)414        self.send_button.clicked.connect(self.send_message)415        416        input_layout.addWidget(self.message_input, 1)417        input_layout.addWidget(self.send_button, 0)418        419        # Add widgets to main layout420        layout.addWidget(self.chat_history, 1)421        layout.addWidget(input_container, 0)422        423        # Set up key event for message input424        self.message_input.installEventFilter(self)425    426    def eventFilter(self, obj, event):427        """Handle key events for message input"""428        if obj == self.message_input and event.type() == event.KeyPress:429            if event.key() == Qt.Key_Return and not event.modifiers() & Qt.ShiftModifier:430                self.send_message()431                return True432        return super().eventFilter(obj, event)433    434    def send_message(self):435        """Send the current message"""436        message = self.message_input.toPlainText().strip()437        if not message:438            return439        440        # Add user message to chat history441        self.add_message(message, is_user=True)442        443        # Clear input field444        self.message_input.clear()445        446        # Call the message callback if provided447        if self.message_callback:448            self.message_callback(message)449    450    def add_message(self, message, is_user=False):451        """Add a message to the chat history"""452        # Format message with appropriate styling453        sender = "You" if is_user else "Vision OS"454        color = "#FFFFFF" if is_user else ColorScheme.ACCENT_BLUE455        456        html = f"""457        <div style="margin-bottom: 10px;">458            <span style="color: {color}; font-weight: bold;">{sender}:</span>459            <div style="margin-left: 10px; margin-top: 5px;">{message}</div>460        </div>461        """462        463        # Add to chat history464        cursor = self.chat_history.textCursor()465        cursor.movePosition(cursor.End)466        cursor.insertHtml(html)467        468        # Scroll to bottom469        self.chat_history.setTextCursor(cursor)470        self.chat_history.ensureCursorVisible()471 472 473class AgentPanel(QWidget):474    """Panel for displaying and interacting with available agents"""475    476    def __init__(self, parent=None, agent_callback=None):477        super().__init__(parent)478        self.agent_callback = agent_callback479        self.setup_ui()480    481    def setup_ui(self):482        """Set up the agent panel UI"""483        layout = QVBoxLayout(self)484        layout.setContentsMargins(0, 0, 0, 0)485        486        # Title487        title = QLabel("Available Agents")488        title.setObjectName("subtitle")489        title.setAlignment(Qt.AlignCenter)490        491        # Agent list492        self.agent_list = QListWidget()493        self.agent_list.setStyleSheet("""494            QListWidget {495                background-color: rgba(20, 24, 33, 0.7);496                border: 1px solid rgba(255, 255, 255, 0.1);497                border-radius: 12px;498                padding: 10px;499            }500            501            QListWidget::item {502                background-color: rgba(30, 36, 50, 0.7);503                border: 1px solid rgba(255, 255, 255, 0.1);504                border-radius: 8px;505                padding: 10px;506                margin-bottom: 5px;507            }508            509            QListWidget::item:selected {510                background-color: rgba(0, 224, 255, 0.2);511                border: 1px solid rgba(0, 224, 255, 0.5);512            }513            514            QListWidget::item:hover {515                background-color: rgba(0, 224, 255, 0.1);516            }517        """)518        519        # Add agents to the list520        self.add_agent("System Agent", "Control your computer and OS", "system")521        self.add_agent("Automation Agent", "Automate web and applications", "automation")522        self.add_agent("File Agent", "Manage and process files", "file")523        self.add_agent("Task Aid Agent", "Manage tasks and projects", "task")524        self.add_agent("Creative Agent", "Generate creative content", "creative")525        self.add_agent("Grant Writer Agent", "Create grant proposals", "grant")526        527        # Connect signals528        self.agent_list.itemClicked.connect(self.on_agent_selected)529        530        # Add widgets to layout531        layout.addWidget(title)532        layout.addWidget(self.agent_list)533    534    def add_agent(self, name, description, agent_id):535        """Add an agent to the list"""536        item = QListWidgetItem()537        item.setData(Qt.UserRole, agent_id)538        539        # Create widget for the item540        widget = QWidget()541        layout = QVBoxLayout(widget)542        layout.setContentsMargins(5, 5, 5, 5)543        544        name_label = QLabel(name)545        name_label.setStyleSheet("font-weight: bold; color: #FFFFFF;")546        547        desc_label = QLabel(description)548        desc_label.setStyleSheet("color: #B0B7C3; font-size: 12px;")549        550        layout.addWidget(name_label)551        layout.addWidget(desc_label)552        553        # Set size hint554        item.setSizeHint(widget.sizeHint())555        556        # Add to list557        self.agent_list.addItem(item)558        self.agent_list.setItemWidget(item, widget)559    560    def on_agent_selected(self, item):561        """Handle agent selection"""562        agent_id = item.data(Qt.UserRole)563        564        if self.agent_callback:565            self.agent_callback(agent_id)566 567 568class MainWindow(QMainWindow):569    """Main window for Vision OS application"""570    571    def __init__(self):572        super().__init__()573        self.setWindowTitle("Vision OS")574        self.setMinimumSize(1200, 800)575        576        # Apply stylesheet577        self.setStyleSheet(StyleSheet.get_base_stylesheet())578        579        # Set up UI580        self.setup_ui()581    582    def setup_ui(self):583        """Set up the main window UI"""584        # Create central widget with particle background585        self.central_widget = ParticleBackground()586        self.setCentralWidget(self.central_widget)587        588        # Main layout589        main_layout = QVBoxLayout(self.central_widget)590        main_layout.setContentsMargins(20, 20, 20, 20)591        main_layout.setSpacing(20)592        593        # Header594        header = QWidget()595        header_layout = QHBoxLayout(header)596        header_layout.setContentsMargins(0, 0, 0, 0)597        598        logo_label = QLabel("VISION OS")599        logo_label.setObjectName("title")600        logo_label.setStyleSheet("""601            QLabel#title {602                font-size: 28px;603                font-weight: bold;604                background: -webkit-linear-gradient(left, #00E0FF, #9D4EDD);605                -webkit-background-clip: text;606                -webkit-text-fill-color: transparent;607            }608        """)609        610        header_layout.addWidget(logo_label)611        header_layout.addStretch(1)612        613        # Create menu buttons614        for text in ["Dashboard", "Settings", "Help"]:615            button = QPushButton(text)616            button.setFlat(True)617            button.setStyleSheet("""618                QPushButton {619                    color: #B0B7C3;620                    border: none;621                    font-size: 16px;622                    padding: 8px 16px;623                }624                QPushButton:hover {625                    color: #FFFFFF;626                }627            """)628            header_layout.addWidget(button)629        630        # Main content area631        content = QWidget()632        content_layout = QHBoxLayout(content)633        content_layout.setContentsMargins(0, 0, 0, 0)634        content_layout.setSpacing(20)635        636        # Left panel (agents)637        left_panel = GlassmorphicPanel()638        left_panel.layout.setContentsMargins(15, 15, 15, 15)639        640        agent_panel = AgentPanel(agent_callback=self.on_agent_selected)641        left_panel.layout.addWidget(agent_panel)642        643        # Center panel (chat)644        center_panel = GlassmorphicPanel()645        center_panel.layout.setContentsMargins(15, 15, 15, 15)646        647        chat_title = QLabel("Vision OS Assistant")648        chat_title.setObjectName("subtitle")649        chat_title.setAlignment(Qt.AlignCenter)650        651        self.chat_panel = ChatPanel(message_callback=self.on_message_sent)652        653        center_panel.layout.addWidget(chat_title)654        center_panel.layout.addWidget(self.chat_panel)655        656        # Right panel (context)657        right_panel = GlassmorphicPanel()658        right_panel.layout.setContentsMargins(15, 15, 15, 15)659        660        context_title = QLabel("Context & Memory")661        context_title.setObjectName("subtitle")662        context_title.setAlignment(Qt.AlignCenter)663        664        self.context_text = QTextEdit()665        self.context_text.setReadOnly(True)666        self.context_text.setPlaceholderText("Context information will appear here...")667        self.context_text.setStyleSheet("""668            QTextEdit {669                background-color: rgba(20, 24, 33, 0.7);670                border: 1px solid rgba(255, 255, 255, 0.1);671                border-radius: 12px;672                padding: 15px;673                font-size: 14px;674            }675        """)676        677        right_panel.layout.addWidget(context_title)678        right_panel.layout.addWidget(self.context_text)679        680        # Add panels to content layout681        content_layout.addWidget(left_panel, 1)682        content_layout.addWidget(center_panel, 2)683        content_layout.addWidget(right_panel, 1)684        685        # Add widgets to main layout686        main_layout.addWidget(header)687        main_layout.addWidget(content, 1)688        689        # Add welcome message690        self.add_welcome_message()691    692    def add_welcome_message(self):693        """Add welcome message to chat"""694        welcome_message = """695        Welcome to Vision OS! I'm your AI assistant, ready to help you with:696        697        • System control and automation698        • Web browsing and data extraction699        • File management and organization700        • Task planning and tracking701        • Creative content generation702        • Grant writing and proposals703        704        How can I assist you today?705        """706        707        self.chat_panel.add_message(welcome_message)708    709    def on_message_sent(self, message):710        """Handle message sent from chat panel"""711        # This would connect to the orchestrator to process the message712        # For now, just echo a response713        import time714        time.sleep(0.5)  # Simulate processing time715        716        response = f"I received your message: '{message}'\n\nI'm processing your request..."717        self.chat_panel.add_message(response)718    719    def on_agent_selected(self, agent_id):720        """Handle agent selection"""721        # Update context panel with agent information722        agent_info = {723            "system": "System Agent can control your computer, execute commands, and manage system resources.",724            "automation": "Automation Agent can automate web browsing, form filling, and data extraction.",725            "file": "File Agent can manage files, organize folders, and process documents.",726            "task": "Task Aid Agent can help you manage tasks, track progress, and break down complex goals.",727            "creative": "Creative Agent can generate various types of creative content like stories, poems, and marketing copy.",728            "grant": "Grant Writer Agent can help you create professional grant proposals and research statements."729        }730        731        if agent_id in agent_info:732            self.context_text.setText(f"Selected Agent: {agent_id.capitalize()} Agent\n\n{agent_info[agent_id]}")733            734            # Also add a message to the chat735            self.chat_panel.add_message(f"You've selected the {agent_id.capitalize()} Agent. How can I help you with this?")736 737 738def launch_app():739    """Launch the Vision OS application"""740    app = QApplication(sys.argv)741    742    # Set application style743    app.setStyle("Fusion")744    745    # Create and show main window746    window = MainWindow()747    window.show()748    749    sys.exit(app.exec_())750 751 752if __name__ == "__main__":753    launch_app()754