Spaces:
Runtime error
Runtime error
| import sys | |
| import os | |
| import sqlite3 | |
| from datetime import datetime | |
| from PyQt6.QtWidgets import ( | |
| QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QLabel, | |
| QStackedWidget, QListWidget, QTextEdit, QLineEdit, QHBoxLayout, QFileDialog, | |
| QCalendarWidget, QMessageBox, QListWidgetItem, QFrame | |
| ) | |
| from PyQt6.QtCore import Qt, QPropertyAnimation, QEasingCurve, QSize | |
| from PyQt6.QtGui import QPixmap, QIcon, QFont, QColor | |
| import folium | |
| from geopy.geocoders import Nominatim | |
| from geopy.exc import GeocoderUnavailable | |
| import requests | |
| from PIL import Image | |
| import io | |
| import base64 | |
| import openai | |
| import configparser | |
| # Configuration setup | |
| config = configparser.ConfigParser() | |
| config.read('config.ini') | |
| # Initialize OpenAI API if key exists | |
| if 'OPENAI' in config and 'api_key' in config['OPENAI']: | |
| openai.api_key = config['OPENAI']['api_key'] | |
| class DatabaseManager: | |
| def __init__(self, db_path='data/tt_travels.db'): | |
| os.makedirs(os.path.dirname(db_path), exist_ok=True) | |
| self.conn = sqlite3.connect(db_path) | |
| self.create_tables() | |
| def create_tables(self): | |
| cursor = self.conn.cursor() | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS trips ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| title TEXT NOT NULL, | |
| start_date TEXT, | |
| end_date TEXT | |
| ) | |
| ''') | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS journal_entries ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| trip_id INTEGER, | |
| title TEXT NOT NULL, | |
| content TEXT, | |
| location TEXT, | |
| timestamp TEXT, | |
| image_path TEXT, | |
| FOREIGN KEY (trip_id) REFERENCES trips(id) | |
| ) | |
| ''') | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS itinerary_items ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| trip_id INTEGER, | |
| day INTEGER, | |
| title TEXT NOT NULL, | |
| description TEXT, | |
| time TEXT, | |
| FOREIGN KEY (trip_id) REFERENCES trips(id) | |
| ) | |
| ''') | |
| self.conn.commit() | |
| def add_trip(self, title, start_date=None, end_date=None): | |
| cursor = self.conn.cursor() | |
| cursor.execute(''' | |
| INSERT INTO trips (title, start_date, end_date) | |
| VALUES (?, ?, ?) | |
| ''', (title, start_date, end_date)) | |
| self.conn.commit() | |
| return cursor.lastrowid | |
| def add_journal_entry(self, trip_id, title, content, location=None, image_path=None): | |
| timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| cursor = self.conn.cursor() | |
| cursor.execute(''' | |
| INSERT INTO journal_entries (trip_id, title, content, location, timestamp, image_path) | |
| VALUES (?, ?, ?, ?, ?, ?) | |
| ''', (trip_id, title, content, location, timestamp, image_path)) | |
| self.conn.commit() | |
| return cursor.lastrowid | |
| def add_itinerary_item(self, trip_id, day, title, description, time=None): | |
| cursor = self.conn.cursor() | |
| cursor.execute(''' | |
| INSERT INTO itinerary_items (trip_id, day, title, description, time) | |
| VALUES (?, ?, ?, ?, ?) | |
| ''', (trip_id, day, title, description, time)) | |
| self.conn.commit() | |
| return cursor.lastrowid | |
| def get_trips(self): | |
| cursor = self.conn.cursor() | |
| cursor.execute('SELECT id, title, start_date, end_date FROM trips') | |
| return cursor.fetchall() | |
| def get_journal_entries(self, trip_id): | |
| cursor = self.conn.cursor() | |
| cursor.execute(''' | |
| SELECT id, title, content, location, timestamp, image_path | |
| FROM journal_entries | |
| WHERE trip_id = ? | |
| ''', (trip_id,)) | |
| return cursor.fetchall() | |
| def get_itinerary(self, trip_id, day=None): | |
| cursor = self.conn.cursor() | |
| if day: | |
| cursor.execute(''' | |
| SELECT id, title, description, time | |
| FROM itinerary_items | |
| WHERE trip_id = ? AND day = ? | |
| ORDER BY time | |
| ''', (trip_id, day)) | |
| else: | |
| cursor.execute(''' | |
| SELECT day, id, title, description, time | |
| FROM itinerary_items | |
| WHERE trip_id = ? | |
| ORDER BY day, time | |
| ''', (trip_id,)) | |
| return cursor.fetchall() | |
| def close(self): | |
| self.conn.close() | |
| class WelcomeWindow(QMainWindow): | |
| def __init__(self): | |
| super().__init__() | |
| self.setWindowTitle("TT's Travels") | |
| self.setFixedSize(800, 500) | |
| self.setStyleSheet(""" | |
| background-color: #2c3e50; | |
| color: #ecf0f1; | |
| """) | |
| central_widget = QWidget() | |
| self.setCentralWidget(central_widget) | |
| layout = QVBoxLayout(central_widget) | |
| layout.setAlignment(Qt.AlignmentFlag.AlignCenter) | |
| # Logo and title | |
| self.logo = QLabel() | |
| self.logo.setAlignment(Qt.AlignmentFlag.AlignCenter) | |
| self.logo.setPixmap(QPixmap("logo.png").scaled(200, 200, Qt.AspectRatioMode.KeepAspectRatio)) | |
| layout.addWidget(self.logo) | |
| title = QLabel("TT's Travels") | |
| title.setFont(QFont("Arial", 32, QFont.Weight.Bold)) | |
| title.setAlignment(Qt.AlignmentFlag.AlignCenter) | |
| layout.addWidget(title) | |
| subtitle = QLabel("Your Personal Travel Companion") | |
| subtitle.setFont(QFont("Arial", 16)) | |
| subtitle.setAlignment(Qt.AlignmentFlag.AlignCenter) | |
| layout.addWidget(subtitle) | |
| # Start button | |
| self.start_btn = QPushButton("Begin Journey") | |
| self.start_btn.setFont(QFont("Arial", 14)) | |
| self.start_btn.setStyleSheet(""" | |
| QPushButton { | |
| background-color: #3498db; | |
| color: white; | |
| border-radius: 15px; | |
| padding: 15px 30px; | |
| } | |
| QPushButton:hover { | |
| background-color: #2980b9; | |
| } | |
| """) | |
| self.start_btn.setFixedSize(200, 50) | |
| self.start_btn.clicked.connect(self.fade_out) | |
| layout.addWidget(self.start_btn, alignment=Qt.AlignmentFlag.AlignCenter) | |
| # Fade-in animation | |
| self.opacity_effect = self.setGraphicsEffect(None) | |
| self.setWindowOpacity(0) | |
| self.fade_in_animation = QPropertyAnimation(self, b"windowOpacity") | |
| self.fade_in_animation.setDuration(1500) | |
| self.fade_in_animation.setStartValue(0) | |
| self.fade_in_animation.setEndValue(1) | |
| self.fade_in_animation.setEasingCurve(QEasingCurve.Type.InOutQuad) | |
| self.fade_in_animation.start() | |
| def fade_out(self): | |
| self.fade_out_animation = QPropertyAnimation(self, b"windowOpacity") | |
| self.fade_out_animation.setDuration(1000) | |
| self.fade_out_animation.setStartValue(1) | |
| self.fade_out_animation.setEndValue(0) | |
| self.fade_out_animation.setEasingCurve(QEasingCurve.Type.InOutQuad) | |
| self.fade_out_animation.finished.connect(self.open_main_app) | |
| self.fade_out_animation.start() | |
| def open_main_app(self): | |
| self.main_app = MainAppWindow() | |
| self.main_app.show() | |
| self.close() | |
| class MainAppWindow(QMainWindow): | |
| def __init__(self): | |
| super().__init__() | |
| self.db = DatabaseManager() | |
| self.setWindowTitle("TT's Travels") | |
| self.setMinimumSize(1000, 700) | |
| # Central stacked widget for modules | |
| self.central_stack = QStackedWidget() | |
| self.setCentralWidget(self.central_stack) | |
| # Setup modules | |
| self.setup_ui() | |
| self.load_trips() | |
| def setup_ui(self): | |
| # Main container widget | |
| main_widget = QWidget() | |
| main_layout = QHBoxLayout(main_widget) | |
| # Sidebar | |
| sidebar = QFrame() | |
| sidebar.setStyleSheet("background-color: #34495e;") | |
| sidebar.setFixedWidth(200) | |
| sidebar_layout = QVBoxLayout(sidebar) | |
| sidebar_layout.setAlignment(Qt.AlignmentFlag.AlignTop) | |
| # Sidebar buttons | |
| modules = [ | |
| ("Journal", self.show_journal), | |
| ("Trip Builder", self.show_trip_builder), | |
| ("Maps", self.show_maps), | |
| ("Weather & AI", self.show_ai), | |
| ("Calendar", self.show_calendar), | |
| ("Export", self.show_export) | |
| ] | |
| for name, callback in modules: | |
| btn = QPushButton(name) | |
| btn.setStyleSheet(""" | |
| QPushButton { | |
| background-color: #2c3e50; | |
| color: white; | |
| padding: 10px; | |
| text-align: left; | |
| border: none; | |
| } | |
| QPushButton:hover { | |
| background-color: #3498db; | |
| } | |
| """) | |
| btn.setFont(QFont("Arial", 12)) | |
| btn.clicked.connect(callback) | |
| sidebar_layout.addWidget(btn) | |
| sidebar_layout.addStretch() | |
| main_layout.addWidget(sidebar) | |
| # Main content area | |
| self.content_stack = QStackedWidget() | |
| main_layout.addWidget(self.content_stack, 1) | |
| # Add modules to content stack | |
| self.journal_widget = JournalWidget(self.db) | |
| self.trip_builder_widget = TripBuilderWidget(self.db) | |
| self.maps_widget = MapsWidget() | |
| self.ai_widget = AIWidget() | |
| self.calendar_widget = CalendarWidget() | |
| self.export_widget = ExportWidget() | |
| self.content_stack.addWidget(self.journal_widget) | |
| self.content_stack.addWidget(self.trip_builder_widget) | |
| self.content_stack.addWidget(self.maps_widget) | |
| self.content_stack.addWidget(self.ai_widget) | |
| self.content_stack.addWidget(self.calendar_widget) | |
| self.content_stack.addWidget(self.export_widget) | |
| self.central_stack.addWidget(main_widget) | |
| def load_trips(self): | |
| trips = self.db.get_trips() | |
| self.journal_widget.load_trips(trips) | |
| self.trip_builder_widget.load_trips(trips) | |
| def show_journal(self): | |
| self.content_stack.setCurrentIndex(0) | |
| def show_trip_builder(self): | |
| self.content_stack.setCurrentIndex(1) | |
| def show_maps(self): | |
| self.content_stack.setCurrentIndex(2) | |
| def show_ai(self): | |
| self.content_stack.setCurrentIndex(3) | |
| def show_calendar(self): | |
| self.content_stack.setCurrentIndex(4) | |
| def show_export(self): | |
| self.content_stack.setCurrentIndex(5) | |
| class JournalWidget(QWidget): | |
| def __init__(self, db): | |
| super().__init__() | |
| self.db = db | |
| self.current_trip_id = None | |
| self.setup_ui() | |
| def setup_ui(self): | |
| layout = QHBoxLayout(self) | |
| # Left panel - Trip selection | |
| left_panel = QWidget() | |
| left_panel.setFixedWidth(250) | |
| left_layout = QVBoxLayout(left_panel) | |
| self.trip_list = QListWidget() | |
| self.trip_list.itemClicked.connect(self.load_journal_entries) | |
| left_layout.addWidget(QLabel("Your Trips:")) | |
| left_layout.addWidget(self.trip_list) | |
| new_trip_btn = QPushButton("New Trip") | |
| new_trip_btn.clicked.connect(self.create_new_trip) | |
| left_layout.addWidget(new_trip_btn) | |
| # Right panel - Journal entries | |
| right_panel = QWidget() | |
| right_layout = QVBoxLayout(right_panel) | |
| self.entry_list = QListWidget() | |
| self.entry_list.itemClicked.connect(self.display_entry) | |
| right_layout.addWidget(QLabel("Journal Entries:")) | |
| right_layout.addWidget(self.entry_list) | |
| # Entry display area | |
| self.entry_display = QTextEdit() | |
| self.entry_display.setReadOnly(True) | |
| right_layout.addWidget(self.entry_display) | |
| # New entry form | |
| entry_form = QWidget() | |
| form_layout = QVBoxLayout(entry_form) | |
| self.entry_title = QLineEdit() | |
| self.entry_title.setPlaceholderText("Title") | |
| form_layout.addWidget(self.entry_title) | |
| self.entry_content = QTextEdit() | |
| self.entry_content.setPlaceholderText("Write your journal entry...") | |
| form_layout.addWidget(self.entry_content) | |
| self.location_entry = QLineEdit() | |
| self.location_entry.setPlaceholderText("Location (optional)") | |
| form_layout.addWidget(self.location_entry) | |
| img_btn = QPushButton("Attach Image") | |
| img_btn.clicked.connect(self.attach_image) | |
| form_layout.addWidget(img_btn) | |
| save_btn = QPushButton("Save Entry") | |
| save_btn.clicked.connect(self.save_entry) | |
| form_layout.addWidget(save_btn) | |
| right_layout.addWidget(entry_form) | |
| layout.addWidget(left_panel) | |
| layout.addWidget(right_panel) | |
| def load_trips(self, trips): | |
| self.trip_list.clear() | |
| for trip_id, title, start_date, end_date in trips: | |
| item = QListWidgetItem(title) | |
| item.setData(Qt.ItemDataRole.UserRole, trip_id) | |
| self.trip_list.addItem(item) | |
| def create_new_trip(self): | |
| title, ok = QInputDialog.getText(self, "New Trip", "Enter trip name:") | |
| if ok and title: | |
| trip_id = self.db.add_trip(title) | |
| self.load_trips(self.db.get_trips()) | |
| def load_journal_entries(self, item): | |
| self.current_trip_id = item.data(Qt.ItemDataRole.UserRole) | |
| entries = self.db.get_journal_entries(self.current_trip_id) | |
| self.entry_list.clear() | |
| for entry_id, title, content, location, timestamp, image_path in entries: | |
| self.entry_list.addItem(f"{timestamp} - {title}") | |
| def display_entry(self, item): | |
| index = self.entry_list.row(item) | |
| entries = self.db.get_journal_entries(self.current_trip_id) | |
| if index < len(entries): | |
| entry = entries[index] | |
| display_text = f"<h2>{entry[1]}</h2>" | |
| display_text += f"<p><i>{entry[4]}</i></p>" | |
| if entry[3]: | |
| display_text += f"<p>Location: {entry[3]}</p>" | |
| display_text += f"<p>{entry[2]}</p>" | |
| if entry[5]: | |
| display_text += f'<img src="{entry[5]}" width="300">' | |
| self.entry_display.setHtml(display_text) | |
| def attach_image(self): | |
| file_path, _ = QFileDialog.getOpenFileName( | |
| self, "Select Image", "", "Images (*.png *.jpg *.jpeg)" | |
| ) | |
| if file_path: | |
| self.image_path = file_path | |
| def save_entry(self): | |
| if not self.current_trip_id: | |
| QMessageBox.warning(self, "No Trip Selected", "Please select a trip first.") | |
| return | |
| title = self.entry_title.text() | |
| content = self.entry_content.toPlainText() | |
| location = self.location_entry.text() | |
| if not title or not content: | |
| QMessageBox.warning(self, "Missing Information", "Title and content are required.") | |
| return | |
| image_path = getattr(self, 'image_path', None) | |
| self.db.add_journal_entry( | |
| self.current_trip_id, title, content, location, image_path | |
| ) | |
| # Reset form | |
| self.entry_title.clear() | |
| self.entry_content.clear() | |
| self.location_entry.clear() | |
| if hasattr(self, 'image_path'): | |
| del self.image_path | |
| # Reload entries | |
| self.load_journal_entries(self.trip_list.currentItem()) | |
| QMessageBox.information(self, "Success", "Journal entry saved!") | |
| class TripBuilderWidget(QWidget): | |
| def __init__(self, db): | |
| super().__init__() | |
| self.db = db | |
| self.current_trip_id = None | |
| self.setup_ui() | |
| def setup_ui(self): | |
| layout = QHBoxLayout(self) | |
| # Left panel - Trip selection | |
| left_panel = QWidget() | |
| left_panel.setFixedWidth(250) | |
| left_layout = QVBoxLayout(left_panel) | |
| self.trip_list = QListWidget() | |
| self.trip_list.itemClicked.connect(self.load_itinerary) | |
| left_layout.addWidget(QLabel("Your Trips:")) | |
| left_layout.addWidget(self.trip_list) | |
| new_trip_btn = QPushButton("New Trip") | |
| new_trip_btn.clicked.connect(self.create_new_trip) | |
| left_layout.addWidget(new_trip_btn) | |
| # Right panel - Itinerary builder | |
| right_panel = QWidget() | |
| right_layout = QVBoxLayout(right_panel) | |
| self.day_selector = QListWidget() | |
| self.day_selector.setMaximumHeight(100) | |
| self.day_selector.itemClicked.connect(self.load_day_items) | |
| right_layout.addWidget(QLabel("Days:")) | |
| right_layout.addWidget(self.day_selector) | |
| self.item_list = QListWidget() | |
| right_layout.addWidget(QLabel("Itinerary Items:")) | |
| right_layout.addWidget(self.item_list) | |
| # Item form | |
| item_form = QWidget() | |
| form_layout = QVBoxLayout(item_form) | |
| self.item_title = QLineEdit() | |
| self.item_title.setPlaceholderText("Activity Title") | |
| form_layout.addWidget(self.item_title) | |
| self.item_desc = QTextEdit() | |
| self.item_desc.setPlaceholderText("Description") | |
| form_layout.addWidget(self.item_desc) | |
| self.item_time = QLineEdit() | |
| self.item_time.setPlaceholderText("Time (e.g., 10:00 AM)") | |
| form_layout.addWidget(self.item_time) | |
| add_btn = QPushButton("Add Item") | |
| add_btn.clicked.connect(self.add_itinerary_item) | |
| form_layout.addWidget(add_btn) | |
| right_layout.addWidget(item_form) | |
| layout.addWidget(left_panel) | |
| layout.addWidget(right_panel) | |
| def load_trips(self, trips): | |
| self.trip_list.clear() | |
| for trip_id, title, start_date, end_date in trips: | |
| item = QListWidgetItem(title) | |
| item.setData(Qt.ItemDataRole.UserRole, trip_id) | |
| self.trip_list.addItem(item) | |
| def create_new_trip(self): | |
| title, ok = QInputDialog.getText(self, "New Trip", "Enter trip name:") | |
| if ok and title: | |
| trip_id = self.db.add_trip(title) | |
| self.load_trips(self.db.get_trips()) | |
| def load_itinerary(self, item): | |
| self.current_trip_id = item.data(Qt.ItemDataRole.UserRole) | |
| self.day_selector.clear() | |
| # Add days 1-10 for simplicity | |
| for day in range(1, 11): | |
| self.day_selector.addItem(f"Day {day}") | |
| self.current_day = 1 | |
| self.load_day_items() | |
| def load_day_items(self, day_item=None): | |
| if day_item: | |
| self.current_day = self.day_selector.row(day_item) + 1 | |
| items = self.db.get_itinerary(self.current_trip_id, self.current_day) | |
| self.item_list.clear() | |
| for item_id, title, description, time in items: | |
| display_text = f"{time}: {title}" if time else title | |
| self.item_list.addItem(display_text) | |
| def add_itinerary_item(self): | |
| if not self.current_trip_id: | |
| QMessageBox.warning(self, "No Trip Selected", "Please select a trip first.") | |
| return | |
| title = self.item_title.text() | |
| description = self.item_desc.toPlainText() | |
| time = self.item_time.text() | |
| if not title: | |
| QMessageBox.warning(self, "Missing Title", "Activity title is required.") | |
| return | |
| self.db.add_itinerary_item( | |
| self.current_trip_id, self.current_day, title, description, time | |
| ) | |
| # Reset form | |
| self.item_title.clear() | |
| self.item_desc.clear() | |
| self.item_time.clear() | |
| # Reload items | |
| self.load_day_items() | |
| QMessageBox.information(self, "Success", "Itinerary item added!") | |
| class MapsWidget(QWidget): | |
| def __init__(self): | |
| super().__init__() | |
| self.setup_ui() | |
| def setup_ui(self): | |
| layout = QVBoxLayout(self) | |
| layout.addWidget(QLabel("Map View (Folium Integration)")) | |
| # Placeholder for folium map | |
| map_label = QLabel("Interactive map will be displayed here") | |
| map_label.setAlignment(Qt.AlignmentFlag.AlignCenter) | |
| map_label.setStyleSheet("background-color: #e0e0e0; padding: 50px;") | |
| layout.addWidget(map_label) | |
| # Location search | |
| search_layout = QHBoxLayout() | |
| self.location_input = QLineEdit() | |
| self.location_input.setPlaceholderText("Enter location") | |
| search_layout.addWidget(self.location_input) | |
| search_btn = QPushButton("Search") | |
| search_btn.clicked.connect(self.search_location) | |
| search_layout.addWidget(search_btn) | |
| layout.addLayout(search_layout) | |
| def search_location(self): | |
| location = self.location_input.text() | |
| if location: | |
| try: | |
| geolocator = Nominatim(user_agent="tt_travels") | |
| location_data = geolocator.geocode(location) | |
| if location_data: | |
| # Create folium map (in a real app, this would be embedded) | |
| m = folium.Map(location=[location_data.latitude, location_data.longitude], zoom_start=13) | |
| folium.Marker( | |
| [location_data.latitude, location_data.longitude], | |
| popup=location | |
| ).add_to(m) | |
| # Save map to HTML and display | |
| map_path = "data/map.html" | |
| m.save(map_path) | |
| QMessageBox.information(self, "Map Generated", f"Map saved to {map_path}") | |
| else: | |
| QMessageBox.warning(self, "Location Not Found", "Could not find the specified location.") | |
| except GeocoderUnavailable: | |
| QMessageBox.critical(self, "Geocoder Error", "Geocoding service unavailable.") | |
| class AIWidget(QWidget): | |
| def __init__(self): | |
| super().__init__() | |
| self.setup_ui() | |
| def setup_ui(self): | |
| layout = QVBoxLayout(self) | |
| layout.addWidget(QLabel("AI Travel Assistant")) | |
| # Weather section | |
| weather_layout = QHBoxLayout() | |
| self.weather_location = QLineEdit() | |
| self.weather_location.setPlaceholderText("Enter location for weather") | |
| weather_layout.addWidget(self.weather_location) | |
| weather_btn = QPushButton("Get Weather") | |
| weather_btn.clicked.connect(self.get_weather) | |
| weather_layout.addWidget(weather_btn) | |
| self.weather_display = QLabel() | |
| self.weather_display.setWordWrap(True) | |
| layout.addLayout(weather_layout) | |
| layout.addWidget(self.weather_display) | |
| # AI suggestions | |
| ai_layout = QVBoxLayout() | |
| ai_layout.addWidget(QLabel("AI Suggestions:")) | |
| self.ai_prompt = QTextEdit() | |
| self.ai_prompt.setPlaceholderText("Ask for travel suggestions...") | |
| ai_layout.addWidget(self.ai_prompt) | |
| ai_btn = QPushButton("Get AI Suggestions") | |
| ai_btn.clicked.connect(self.get_ai_suggestions) | |
| ai_layout.addWidget(ai_btn) | |
| self.ai_response = QTextEdit() | |
| self.ai_response.setReadOnly(True) | |
| ai_layout.addWidget(self.ai_response) | |
| layout.addLayout(ai_layout) | |
| def get_weather(self): | |
| location = self.weather_location.text() | |
| if location: | |
| try: | |
| # Using Open-Meteo API for example | |
| geolocator = Nominatim(user_agent="tt_travels") | |
| loc = geolocator.geocode(location) | |
| if loc: | |
| url = f"https://api.open-meteo.com/v1/forecast?latitude={loc.latitude}&longitude={loc.longitude}¤t_weather=true" | |
| response = requests.get(url) | |
| if response.status_code == 200: | |
| data = response.json() | |
| current = data.get('current_weather', {}) | |
| temp = current.get('temperature', 'N/A') | |
| windspeed = current.get('windspeed', 'N/A') | |
| weather_code = current.get('weathercode', 'N/A') | |
| self.weather_display.setText( | |
| f"Current weather in {location}: {temp}°C, Wind: {windspeed} km/h" | |
| ) | |
| else: | |
| self.weather_display.setText("Weather data unavailable.") | |
| else: | |
| self.weather_display.setText("Location not found.") | |
| except Exception as e: | |
| self.weather_display.setText(f"Error: {str(e)}") | |
| def get_ai_suggestions(self): | |
| if not openai.api_key: | |
| self.ai_response.setText("OpenAI API key not configured.") | |
| return | |
| prompt = self.ai_prompt.toPlainText() | |
| if not prompt: | |
| self.ai_response.setText("Please enter a prompt.") | |
| return | |
| try: | |
| response = openai.ChatCompletion.create( | |
| model="gpt-3.5-turbo", | |
| messages=[{"role": "user", "content": prompt}], | |
| max_tokens=500 | |
| ) | |
| self.ai_response.setText(response.choices[0].message['content'].strip()) | |
| except Exception as e: | |
| self.ai_response.setText(f"Error: {str(e)}") | |
| class CalendarWidget(QWidget): | |
| def __init__(self): | |
| super().__init__() | |
| self.setup_ui() | |
| def setup_ui(self): | |
| layout = QVBoxLayout(self) | |
| layout.addWidget(QLabel("Travel Calendar")) | |
| self.calendar = QCalendarWidget() | |
| layout.addWidget(self.calendar) | |
| # Event list | |
| self.event_list = QListWidget() | |
| layout.addWidget(self.event_list) | |
| # Import button | |
| import_btn = QPushButton("Import ICS File") | |
| import_btn.clicked.connect(self.import_ics) | |
| layout.addWidget(import_btn) | |
| def import_ics(self): | |
| file_path, _ = QFileDialog.getOpenFileName( | |
| self, "Import Calendar", "", "ICS Files (*.ics)" | |
| ) | |
| if file_path: | |
| # Placeholder for ICS parsing | |
| self.event_list.addItem(f"Imported: {os.path.basename(file_path)}") | |
| QMessageBox.information(self, "Import Successful", "Calendar events imported!") | |
| class ExportWidget(QWidget): | |
| def __init__(self): | |
| super().__init__() | |
| self.setup_ui() | |
| def setup_ui(self): | |
| layout = QVBoxLayout(self) | |
| layout.addWidget(QLabel("Export Data")) | |
| # Export options | |
| options = [ | |
| ("Export Journal as PDF", self.export_journal_pdf), | |
| ("Export Trip as CSV", self.export_trip_csv), | |
| ("Export All Data", self.export_all) | |
| ] | |
| for text, callback in options: | |
| btn = QPushButton(text) | |
| btn.clicked.connect(callback) | |
| layout.addWidget(btn) | |
| def export_journal_pdf(self): | |
| QMessageBox.information(self, "Export", "Journal PDF export functionality would be implemented here.") | |
| def export_trip_csv(self): | |
| QMessageBox.information(self, "Export", "Trip CSV export functionality would be implemented here.") | |
| def export_all(self): | |
| QMessageBox.information(self, "Export", "Full data export functionality would be implemented here.") | |
| if __name__ == "__main__": | |
| app = QApplication(sys.argv) | |
| # Set application style | |
| app.setStyle("Fusion") | |
| welcome = WelcomeWindow() | |
| welcome.show() | |
| sys.exit(app.exec()) |