flen-crypto's picture
Upload app.py with huggingface_hub
03c3fed verified
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}&current_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())