def start_background_services(self):
"""Start background services"""
# Auto-save service
if self.settings.get("auto_save", True):
self.root.after(300000, self.auto_save_all) # Every 5
minutes
# System monitoring
self.root.after(5000, self.update_system_stats) # Every 5
seconds
# Auto-backup service
if self.settings.get("auto_backup", True):
self.root.after(1800000, self.create_auto_backup) # Every
30 minutes
def auto_save_all(self):
"""Auto-save all open documents"""
try:
# Save current work
if hasattr(self, 'current_doc_content'):
self.save_current_document()
self.update_status("Auto-save completed")
# Schedule next auto-save
if self.settings.get("auto_save", True):
self.root.after(300000, self.auto_save_all)
except Exception as e:
print(f"Auto-save error: {e}")
def update_system_stats(self):
"""Update system statistics"""
try:
cpu_percent = psutil.cpu_percent()
memory_percent = psutil.virtual_memory().percent
# Update status bar
for widget in self.status_frame.winfo_children():
if isinstance(widget, ctk.CTkLabel) and "CPU:" in
widget.cget("text"):
widget.configure(text=f"CPU: {cpu_percent}% | RAM:
{memory_percent}% | Quarix AI: Active")
break
# Schedule next update
self.root.after(5000, self.update_system_stats)
except Exception as e:
print(f"System stats error: {e}")
def create_auto_backup(self):
"""Create automatic backup"""
try:
backup_dir = "quarix_backups"
if not os.path.exists(backup_dir):
os.makedirs(backup_dir)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_file =
f"{backup_dir}/quarix_backup_{timestamp}.zip"
with zipfile.ZipFile(backup_file, 'w') as zipf:
zipf.write('quarix_office.db')
if os.path.exists('quarix_settings.json'):
zipf.write('quarix_settings.json')
self.update_status(f"Auto-backup created: {backup_file}")
# Schedule next backup
if self.settings.get("auto_backup", True):
self.root.after(1800000, self.create_auto_backup)
except Exception as e:
print(f"Auto-backup error: {e}")
def update_status(self, message):
"""Update status bar message"""
if hasattr(self, 'status_label'):
self.status_label.configure(text=message)
# Clear status after 5 seconds
self.root.after(5000, lambda:
self.status_label.configure(text="Ready"))
def clear_content(self):
"""Clear main content area"""
for widget in self.content_frame.winfo_children():
widget.destroy()
def show_chat_with_quarix(self):
"""Show enhanced Chat with Quarix interface"""
self.clear_content()
# Title with enhanced styling
title_frame = ctk.CTkFrame(self.content_frame,
fg_color="transparent")
title_frame.pack(fill="x", padx=10, pady=5)
# PUT YOUR QUARIX CHAT AVATAR/ICON HERE:
# try:
# avatar_image = Image.open("quarix_avatar.png") #
Replace with your avatar path
# avatar_image = avatar_image.resize((48, 48),
Image.Resampling.LANCZOS)
# avatar_photo = ImageTk.PhotoImage(avatar_image)
# avatar_label = ctk.CTkLabel(title_frame,
image=avatar_photo, text="")
# avatar_label.pack(side="left", padx=10)
# self.avatar_photo = avatar_photo # Keep reference
# except:
# Fallback avatar
avatar_frame = ctk.CTkFrame(title_frame, width=48, height=48,
corner_radius=24)
avatar_frame.pack(side="left", padx=10)
avatar_frame.pack_propagate(False)
ctk.CTkLabel(avatar_frame, text="🤖", font=("Arial",
24)).pack(expand=True)
title_text_frame = ctk.CTkFrame(title_frame,
fg_color="transparent")
title_text_frame.pack(side="left", padx=10)
ctk.CTkLabel(title_text_frame, text="Chat with Quarix AI",
font=("Arial", 28, "bold"),
text_color="#00ff88").pack(anchor="w")
ctk.CTkLabel(title_text_frame, text="Your Advanced AI Office
Assistant",
font=("Arial", 12),
text_color="gray").pack(anchor="w")
# Chat controls with enhanced features
controls_frame = ctk.CTkFrame(title_frame)
controls_frame.pack(side="right", padx=10)
control_buttons = [
(" Clear", self.clear_chat),
("💾 Save", self.save_chat),
("📤 Export", self.export_chat),
("🎤 Voice", self.toggle_voice_chat),
("⚙️Settings", self.chat_settings)
]
for text, command in control_buttons:
ctk.CTkButton(controls_frame, text=text, command=command,
width=80, height=35, font=("Arial",
10)).pack(side="left", padx=2)
# Chat display area with enhanced styling
chat_container = ctk.CTkFrame(self.content_frame)
chat_container.pack(fill="both", expand=True, padx=10, pady=5)
# Chat history with scrollbar
self.chat_display = ctk.CTkTextbox(
chat_container,
font=("Arial", 12),
wrap="word",
corner_radius=10
)
self.chat_display.pack(fill="both", expand=True, padx=10,
pady=10)
# Enhanced welcome message
welcome_msg = """🤖 Quarix AI: Greetings! I'm Quarix, your
advanced AI office assistant.
I'm here to revolutionize your productivity experience! Here's what I
can help you with:
📄 DOCUMENT ASSISTANCE
• Professional writing and editing
• Grammar and style improvements
• Content generation and brainstorming
• Document formatting and structure
📊 DATA & ANALYTICS
• Spreadsheet formulas and calculations
• Data analysis and visualization
• Business insights and recommendations
• Statistical analysis and reporting
📋 PRESENTATIONS
• Slide content creation
• Design suggestions and layouts
• Speaker notes and talking points
• Visual storytelling techniques
🔍 RESEARCH & LEARNING
• Information gathering and synthesis
• Market research and analysis
• Technical explanations
• Educational content creation
💡 CREATIVE SOLUTIONS
• Problem-solving strategies
• Innovation and brainstorming
• Process optimization
• Creative project ideas
TECHNICAL SUPPORT
• Software troubleshooting
• Workflow optimization
• Integration solutions
• Best practices guidance
I learn from our conversations to provide increasingly personalized
assistance. What would you like to accomplish today? I'm excited to
help you achieve your goals! ✨
"""
self.chat_display.insert("0.0", welcome_msg)
self.chat_display.configure(state="disabled")
# Enhanced input area
input_container = ctk.CTkFrame(self.content_frame)
input_container.pack(fill="x", padx=10, pady=5)
# Quick action buttons
quick_actions_frame = ctk.CTkFrame(input_container)
quick_actions_frame.pack(fill="x", padx=10, pady=5)
ctk.CTkLabel(quick_actions_frame, text="Quick Actions:",
font=("Arial", 12, "bold")).pack(side="left",
padx=5)
quick_actions = [
("📝 Help Write", "Help me write a professional document
about"),
("📊 Analyze Data", "I need help analyzing data that
shows"),
("🎨 Design Ideas", "Give me creative design ideas for"),
("🔍 Research", "Help me research information about"),
("💡 Brainstorm", "Let's brainstorm ideas for"),
(" Solve Problem", "I need help solving this problem:")
]
for text, prompt in quick_actions:
ctk.CTkButton(
quick_actions_frame,
text=text,
command=lambda p=prompt: self.quick_chat(p),
width=100,
height=30,
font=("Arial", 9)
).pack(side="left", padx=2)
# Message input with enhanced features
input_frame = ctk.CTkFrame(input_container)
input_frame.pack(fill="x", padx=10, pady=5)
# Input label
ctk.CTkLabel(input_frame, text="Message Quarix:",
font=("Arial", 12, "bold")).pack(anchor="w",
padx=5, pady=(5,0))
# Text input area
self.chat_input = ctk.CTkTextbox(
input_frame,
height=100,
font=("Arial", 12),
corner_radius=8,
placeholder_text="Type your message here... (Ctrl+Enter to
send)"
)
self.chat_input.pack(fill="x", padx=5, pady=5)
self.chat_input.bind("<Control-Return>", lambda e:
self.send_chat_message())
self.chat_input.bind("<KeyRelease>", self.on_input_change)
# Input controls
input_controls = ctk.CTkFrame(input_frame)
input_controls.pack(fill="x", padx=5, pady=5)
# Character counter
self.char_counter = ctk.CTkLabel(input_controls, text="0
characters",
font=("Arial", 10),
text_color="gray")
self.char_counter.pack(side="left")
# Send button with enhanced styling
send_frame = ctk.CTkFrame(input_controls)
send_frame.pack(side="right")
self.send_button = ctk.CTkButton(
send_frame,
text="🚀 Send Message",
command=self.send_chat_message,
width=150,
height=40,
font=("Arial", 12, "bold"),
fg_color="#00ff88",
hover_color="#00dd77",
text_color="black"
)
self.send_button.pack(padx=5)
# Typing indicator
self.typing_indicator = ctk.CTkLabel(
input_controls,
text="",
font=("Arial", 10, "italic"),
text_color="#00ff88"
)
self.typing_indicator.pack(side="right", padx=10)
# Status and features
status_frame = ctk.CTkFrame(self.content_frame)
status_frame.pack(fill="x", padx=10, pady=2)
self.chat_status = ctk.CTkLabel(status_frame, text="🟢 Quarix
AI Online - Ready to assist",
anchor="w", font=("Arial", 11))
self.chat_status.pack(side="left", padx=10, pady=5)
# Features indicator
features_text = "✨ Voice Chat | 🧠 Smart Suggestions | 💾 Auto-
Save | 🔒 Secure"
features_label = ctk.CTkLabel(status_frame,
text=features_text,
anchor="e", font=("Arial", 9),
text_color="gray")
features_label.pack(side="right", padx=10, pady=5)
# Load chat history
self.load_chat_history()
# Initialize chat session
self.current_session_id = datetime.now().strftime("%Y%m%d_%H%M
%S")
# Start Quarix AI session
threading.Thread(target=self.initialize_quarix_session,
daemon=True).start()
def initialize_quarix_session(self):
"""Initialize Quarix AI chat session"""
try:
self.ai.start_chat_session()
self.root.after(0, lambda: self.chat_status.configure(
text="🟢 Quarix AI Initialized - Enhanced mode active"
))
except Exception as e:
self.root.after(0, lambda: self.chat_status.configure(
text=f"⚠️Quarix AI Warning: {str(e)}"
))
def on_input_change(self, event=None):
"""Handle input text changes"""
text = self.chat_input.get("0.0", "end-1c")
char_count = len(text)
self.char_counter.configure(text=f"{char_count} characters")
# Show typing indicator
if char_count > 0:
self.typing_indicator.configure(text="✍️Typing...")
else:
self.typing_indicator.configure(text="")
def quick_chat(self, prompt_start):
"""Send a quick chat message with prompt"""
self.chat_input.delete("0.0", "end")
self.chat_input.insert("0.0", prompt_start + " ")
self.chat_input.focus()
def send_chat_message(self):
"""Send message to Quarix AI with enhanced features"""
message = self.chat_input.get("0.0", "end-1c").strip()
if not message:
return
# Clear input
self.chat_input.delete("0.0", "end")
self.char_counter.configure(text="0 characters")
self.typing_indicator.configure(text="")
# Disable send button temporarily
self.send_button.configure(state="disabled",
text="Sending...")
# Add user message to display with enhanced formatting
timestamp = datetime.now().strftime("%H:%M:%S")
self.add_message_to_chat("user", message, timestamp)
# Update status
self.chat_status.configure(text="🤔 Quarix is thinking deeply
about your request...")
# Show thinking animation
self.show_thinking_animation()
# Send to AI in background
threading.Thread(target=self.process_chat_message,
args=(message,), daemon=True).start()
def add_message_to_chat(self, sender, message, timestamp):
"""Add formatted message to chat display"""
self.chat_display.configure(state="normal")
if sender == "user":
# User message formatting
self.chat_display.insert("end", f"\n\n👤 You
({timestamp}):\n")
self.chat_display.insert("end", f"{message}\n")
else:
# Quarix message formatting
self.chat_display.insert("end", f"\n🤖 Quarix
({timestamp}):\n")
self.chat_display.insert("end", f"{message}\n")
self.chat_display.configure(state="disabled")
self.chat_display.see("end")
def show_thinking_animation(self):
"""Show Quarix thinking animation"""
thinking_states = [
"🤔 Quarix is thinking.",
"🤔 Quarix is thinking..",
"🤔 Quarix is thinking...",
"🧠 Quarix is analyzing...",
"💭 Quarix is formulating response...",
"✨ Quarix is crafting the perfect answer..."
]
self.thinking_step = 0
self.animate_thinking(thinking_states)
def animate_thinking(self, states):
"""Animate thinking indicator"""
if hasattr(self, 'thinking_active') and self.thinking_active:
if self.thinking_step < len(states):
self.chat_status.configure(text=states[self.thinking_step])
self.thinking_step = (self.thinking_step + 1) %
len(states)
self.root.after(500, lambda:
self.animate_thinking(states))
def process_chat_message(self, message):
"""Process chat message with enhanced Quarix AI"""
try:
self.thinking_active = True
# Enhanced context for Quarix
enhanced_context = f"""
Remember, you are Quarix, the advanced AI assistant for
Quarix Office.
Current session: {self.current_session_id}
User's current workspace:
{self.get_current_workspace_context()}
Respond as Quarix with your full personality - be helpful,
intelligent, creative, and professional.
Always aim to provide actionable, specific advice while
maintaining your friendly yet professional demeanor.
User message: {message}
"""
# Get response from Gemini with Quarix personality
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
response =
loop.run_until_complete(self.ai.chat_response(enhanced_context))
loop.close()
# Stop thinking animation
self.thinking_active = False
# Add AI response to display
timestamp = datetime.now().strftime("%H:%M:%S")
self.root.after(0, self.add_message_to_chat, "quarix",
response, timestamp)
# Save to database with enhanced metadata
self.save_chat_to_db(message, response)
# Analyze message for insights
self.analyze_chat_for_insights(message, response)
except Exception as e:
self.thinking_active = False
error_msg = f"I apologize, but I encountered a technical
issue: {str(e)}. Please try again, and if the problem persists, check
your internet connection or API settings."
timestamp = datetime.now().strftime("%H:%M:%S")
self.root.after(0, self.add_message_to_chat, "quarix",
error_msg, timestamp)
# Re-enable send button and update status
self.root.after(0, self.reset_chat_interface)
def get_current_workspace_context(self):
"""Get context about current workspace"""
context = []
# Check what's currently open
if hasattr(self, 'current_document') and
self.current_document:
context.append("Document editor is open")
if hasattr(self, 'current_spreadsheet') and
self.current_spreadsheet:
context.append("Spreadsheet is active")
# Get recent activity
try:
self.cursor.execute(
"SELECT event_type FROM analytics WHERE timestamp >
datetime('now', '-1 hour') ORDER BY timestamp DESC LIMIT 5"
)
recent_activity = [row[0] for row in
self.cursor.fetchall()]
if recent_activity:
context.append(f"Recent activity: {',
'.join(recent_activity)}")
except:
pass
return "; ".join(context) if context else "General office
work"
def analyze_chat_for_insights(self, message, response):
"""Analyze chat for user insights and preferences"""
try:
# Categorize the conversation
categories = {
"document": ["write", "document", "text", "edit",
"grammar"],
"data": ["data", "spreadsheet", "formula",
"calculate", "analyze"],
"presentation": ["presentation", "slide", "present",
"design"],
"creative": ["creative", "idea", "brainstorm",
"design", "innovative"],
"technical": ["technical", "problem", "error", "fix",
"troubleshoot"],
"research": ["research", "information", "find",
"learn", "study"]
}
message_lower = message.lower()
detected_category = "general"
for category, keywords in categories.items():
if any(keyword in message_lower for keyword in
keywords):
detected_category = category
break
# Save analytics
analytics_data = {
"message_length": len(message),
"response_length": len(response),
"category": detected_category,
"session_id": self.current_session_id
}
self.cursor.execute(
"INSERT INTO analytics (event_type, event_data,
timestamp, user_session) VALUES (?, ?, ?, ?)",
("chat_interaction", json.dumps(analytics_data),
datetime.now().isoformat(), self.current_session_id)
)
self.conn.commit()
except Exception as e:
print(f"Analytics error: {e}")
def reset_chat_interface(self):
"""Reset chat interface after message processing"""
self.send_button.configure(state="normal", text="🚀 Send
Message")
self.chat_status.configure(text="🟢 Quarix AI Ready - How can I
help you next?")
def save_chat_to_db(self, message, response):
"""Save chat to database with enhanced metadata"""
try:
timestamp = datetime.now().isoformat()
# Determine category
categories = ["document", "data", "presentation",
"creative", "technical", "research", "general"]
message_lower = message.lower()
category = "general"
category_keywords = {
"document": ["write", "document", "text", "edit"],
"data": ["data", "spreadsheet", "formula", "analyze"],
"presentation": ["presentation", "slide", "present"],
"creative": ["creative", "idea", "brainstorm",
"design"],
"technical": ["technical", "problem", "error", "fix"],
"research": ["research", "information", "find",
"learn"]
}
for cat, keywords in category_keywords.items():
if any(keyword in message_lower for keyword in
keywords):
category = cat
break
self.cursor.execute(
"INSERT INTO chat_history (message, response,
timestamp, session_id, category) VALUES (?, ?, ?, ?, ?)",
(message, response, timestamp,
self.current_session_id, category)
)
self.conn.commit()
except Exception as e:
print(f"Error saving chat: {e}")
def load_chat_history(self):
"""Load recent chat history with enhanced formatting"""
try:
self.cursor.execute(
"SELECT message, response, timestamp, category FROM
chat_history ORDER BY id DESC LIMIT 5"
)
history = self.cursor.fetchall()
if history:
self.chat_display.configure(state="normal")
self.chat_display.insert("end", "\n" + "="*60)
self.chat_display.insert("end", "\n📚 Recent
Conversation History")
self.chat_display.insert("end", "\n" + "="*60 + "\n")
for message, response, timestamp, category in
reversed(history):
try:
dt = datetime.fromisoformat(timestamp)
time_str = dt.strftime("%H:%M")
date_str = dt.strftime("%Y-%m-%d")
category_emoji = {
"document": "📄", "data": "📊",
"presentation": "📋",
"creative": "🎨", "technical": "",
"research": "🔍"
}.get(category, "💬")
self.chat_display.insert("end", f"\
n{category_emoji} [{date_str} {time_str}] You:\n{message}\n")
self.chat_display.insert("end", f"\n🤖 Quarix:\
n{response}\n")
self.chat_display.insert("end", "\n" + "-"*40
+ "\n")
except:
continue
self.chat_display.insert("end", "\n" + "="*60)
self.chat_display.insert("end", "\n🆕 Current Session")
self.chat_display.insert("end", "\n" + "="*60 + "\n")
self.chat_display.configure(state="disabled")
except Exception as e:
print(f"Error loading chat history: {e}")
def toggle_voice_chat(self):
"""Toggle voice chat functionality"""
if not self.voice_enabled:
messagebox.showwarning("Voice Chat", "Voice chat is not
available. Please install required packages.")
return
# Create voice chat dialog
voice_dialog = ctk.CTkToplevel(self.root)
voice_dialog.title("Voice Chat with Quarix")
voice_dialog.geometry("400x300")
voice_dialog.transient(self.root)
ctk.CTkLabel(voice_dialog, text="🎤 Voice Chat", font=("Arial",
20, "bold")).pack(pady=20)
self.voice_status = ctk.CTkLabel(voice_dialog, text="Click
'Start Listening' to begin",
font=("Arial", 12))
self.voice_status.pack(pady=10)
# Voice controls
voice_controls = ctk.CTkFrame(voice_dialog)
voice_controls.pack(pady=20)
ctk.CTkButton(voice_controls, text="🎤 Start Listening",
command=self.start_voice_recognition).pack(pady=5)
ctk.CTkButton(voice_controls, text="🔊 Test Speech",
command=self.test_text_to_speech).pack(pady=5)
ctk.CTkButton(voice_controls, text="⚙️Voice Settings",
command=self.voice_settings).pack(pady=5)
def start_voice_recognition(self):
"""Start voice recognition"""
if not self.voice_enabled:
return
def recognize_speech():
try:
self.voice_status.configure(text="🎤 Listening... Speak
now!")
with self.microphone as source:
self.recognizer.adjust_for_ambient_noise(source)
audio = self.recognizer.listen(source, timeout=10)
self.voice_status.configure(text="🔄 Processing
speech...")
text = self.recognizer.recognize_google(audio)
self.root.after(0, lambda:
self.chat_input.insert("end", text))
self.root.after(0, lambda:
self.voice_status.configure(text=f"✅ Recognized: {text[:50]}..."))
except sr.WaitTimeoutError:
self.root.after(0, lambda:
self.voice_status.configure(text="⏰ Timeout - No speech detected"))
except sr.UnknownValueError:
self.root.after(0, lambda:
self.voice_status.configure(text="❌ Could not understand speech"))
except Exception as e:
self.root.after(0, lambda:
self.voice_status.configure(text=f"❌ Error: {str(e)}"))
threading.Thread(target=recognize_speech, daemon=True).start()
def test_text_to_speech(self):
"""Test text-to-speech"""
if not self.voice_enabled:
return
def speak():
try:
self.tts_engine.say("Hello! I'm Quarix, your AI
assistant. Voice chat is working perfectly!")
self.tts_engine.runAndWait()
except Exception as e:
print(f"TTS error: {e}")
threading.Thread(target=speak, daemon=True).start()
def voice_settings(self):
"""Voice settings dialog"""
settings_dialog = ctk.CTkToplevel(self.root)
settings_dialog.title("Voice Settings")
settings_dialog.geometry("350x250")
settings_dialog.transient(self.root)
ctk.CTkLabel(settings_dialog, text="Voice Settings",
font=("Arial", 16, "bold")).pack(pady=10)
# Voice speed
ctk.CTkLabel(settings_dialog, text="Speech
Speed:").pack(pady=5)
speed_slider = ctk.CTkSlider(settings_dialog, from_=50,
to=300, number_of_steps=25)
speed_slider.set(150)
speed_slider.pack(pady=5)
# Voice volume
ctk.CTkLabel(settings_dialog, text="Volume:").pack(pady=5)
volume_slider = ctk.CTkSlider(settings_dialog, from_=0, to=1,
number_of_steps=10)
volume_slider.set(0.8)
volume_slider.pack(pady=5)
def apply_settings():
if self.voice_enabled:
self.tts_engine.setProperty('rate',
int(speed_slider.get()))
self.tts_engine.setProperty('volume',
volume_slider.get())
settings_dialog.destroy()
ctk.CTkButton(settings_dialog, text="Apply Settings",
command=apply_settings).pack(pady=20)
def chat_settings(self):
"""Chat settings dialog"""
settings_dialog = ctk.CTkToplevel(self.root)
settings_dialog.title("Chat Settings")
settings_dialog.geometry("500x400")
settings_dialog.transient(self.root)
ctk.CTkLabel(settings_dialog, text="Quarix Chat Settings",
font=("Arial", 18, "bold")).pack(pady=15)
# Settings notebook
notebook = ttk.Notebook(settings_dialog)
notebook.pack(fill="both", expand=True, padx=20, pady=10)
# General tab
general_frame = ctk.CTkFrame(notebook)
notebook.add(general_frame, text="General")
# AI Personality settings
ctk.CTkLabel(general_frame, text="AI Response Style:",
font=("Arial", 12, "bold")).pack(pady=5)
style_var = tk.StringVar(value="Professional")
styles = ["Professional", "Casual", "Technical", "Creative",
"Detailed"]
style_menu = ctk.CTkOptionMenu(general_frame,
variable=style_var, values=styles)
style_menu.pack(pady=5)
# Response length
ctk.CTkLabel(general_frame, text="Response Length:",
font=("Arial", 12, "bold")).pack(pady=5)
length_var = tk.StringVar(value="Balanced")
lengths = ["Concise", "Balanced", "Detailed", "Comprehensive"]
length_menu = ctk.CTkOptionMenu(general_frame, variable