import pygame
import openpyxl
from datetime import date, timedelta
from bidi.algorithm import get_display # Import the get_display function for text mirroring
from datetime import datetime
from openpyxl.utils.dataframe import dataframe_to_rows
from operator import itemgetter
import pygame.colordict
import sys
# Initialize Pygame
pygame.init()
# Set up the display
screen = pygame.display.set_mode((800, 600))
button_width = 30
button_hight = 30
pygame.display.set_caption("Speech Organizer")
file_path = r"C:\Users\user\Downloads\speech maneger\speeches.xlsx"
occupied_dates_file = r"C:\Users\user\Downloads\speech maneger\occupied_dates.txt"
# Import images
search_button_initial_image = pygame.image.load(r"C:\Users\user\Downloads\speech maneger\Magnifying Glass.png")
search_button_hover_image = pygame.image.load(r"C:\Users\user\Downloads\speech maneger\Magnifying Glass hover.png")
search_button_initial_image = pygame.transform.scale(search_button_initial_image, (button_width,button_hight))
search_button_hover_image = pygame.transform.scale(search_button_hover_image, (button_width,button_hight))
logo_image = pygame.image.load(r"C:\Users\user\Downloads\speech maneger\לוגו למנהל נאומים לוגו.png")
logo_image = pygame.transform.scale(logo_image, (50, 50))
# Colors
BACKGROUND_COLOR = (242, 242, 242)
INPUT_COLOR = (220, 220, 220)
TEXT_COLOR = (30, 30, 30)
CURSOR_COLOR = (0, 0, 0)
PRIMARY_COLOR = (74, 144, 226)
SECONDARY_COLOR = (255, 120, 82)
BUTTON_COLOR = (35, 35, 35)
MENU_COLOR = (74, 144, 226)
# Load a font that supports English and Hebrew characters
FONT_PATH = r"C:\Users\user\Downloads\tahoma.ttf"
FONT_SIZE = 36
FONT = pygame.font.Font(FONT_PATH, FONT_SIZE)
FONT2 = pygame.font.Font(FONT_PATH, 50)
# Load recets
logo_rect = (screen.get_width() - logo_image.get_width() - 10, 10)
menu_button_rect = pygame.Rect(screen.get_width() - 780, 20, 30, 30)
s1_menu_button_rect = pygame.Rect(screen.get_width() - 780, 20, 30, 3)
search_button_rect = search_button_initial_image.get_rect(center=(230, 30))
search_input_rect = pygame.Rect(50, 140, 700, 50)
# Variables
menu_width = 300
mouse_x, mouse_y = pygame.mouse.get_pos()
running = True
input_name = ""
input_topic = ""
input_phone = ""
input_date = ""
active_input = "name"
cursor_visible = True
cursor_timer = 0
menu_open = False
search_open = False
# Load the existing Excel file or create a new one if it doesn't exist
try:
workbook = openpyxl.load_workbook(file_path)
except FileNotFoundError:
workbook = openpyxl.Workbook()
sheet = workbook.active
sheet.title = 'Speeches'
def button_animation(button_rect, button_initial, button_hover):
if button_rect.collidepoint(mouse_x, mouse_y): # Check if mouse is hovering over the replay button
screen.blit(button_hover, button_rect) # Blit the hover state image
else:
screen.blit(button_initial, button_rect) # Blit the initial state image
# Find the next available Saturday
def find_next_available_saturday(current_date):
with open(occupied_dates_file, 'r') as f:
occupied_dates = [line.strip() for line in f]
while current_date.weekday() != 5 or str(current_date) in occupied_dates:
current_date += timedelta(days=1)
return current_date
def is_hebrew(sentence):
for char in sentence:
if not ('\u0590' <= char <= '\u05FF'):
return False
return True
def draw_menu_button():
pygame.draw.rect(screen, BUTTON_COLOR, s1_menu_button_rect)
pygame.draw.rect(screen, BUTTON_COLOR, s1_menu_button_rect.move(0, 10))
pygame.draw.rect(screen, BUTTON_COLOR, s1_menu_button_rect.move(0, 20))
def search_button():
screen.blit(search_button_initial_image ,search_button_rect)
button_animation(search_button_rect, search_button_initial_image, search_button_hover_image)
def search_button_sc(scroll_y):
search_button_rect = search_button_initial_image.get_rect(center=(230, 30))
screen.blit(search_button_initial_image, (search_button_rect.x, search_button_rect.y + scroll_y))
button_animation(search_button_rect, search_button_initial_image, search_button_hover_image)
def menu_logic():
# Adjust the position of other elements based on the menu state
if menu_open:
input_rect_x = 50 + menu_width
input_label_text_x = 50 + menu_width
s1_menu_button_rect.x = menu_width - 40
menu_button_rect.x = menu_width - 40
# Draw the menu window
menu_rect = pygame.Rect(0, 0, menu_width, screen.get_height())
pygame.draw.rect(screen, MENU_COLOR, menu_rect)
draw_menu_button()
search_button()
else:
# Adjust the position of other elements based on the menu state
logo_rect = (screen.get_width() - logo_image.get_width() - 10, 10)
s1_menu_button_rect.x = screen.get_width() - 780
menu_button_rect.x = screen.get_width() - 780
def cursor_logic():
global cursor_timer
global cursor_visible
global search_input_rect
# Cursor blinking
cursor_timer += 0.2
if cursor_timer >= 30:
cursor_timer = 0
cursor_visible = not cursor_visible
if cursor_visible:
cursor_x = input_rect.x + 10 # Default cursor position
if active_input != "date": # Adjust cursor position for non-date inputs
cursor_x += input_text_surface.get_width()
cursor_y = input_rect.y + 10
pygame.draw.rect(screen, CURSOR_COLOR, (cursor_x, cursor_y, 2, 36))
def draw_logo_and_header():
# Draw the logo and header
pygame.draw.rect(screen, (255, 255, 255), (0, 0, screen.get_width(), 70))
logo_rect = (screen.get_width() - logo_image.get_width() - 10, 10)
draw_menu_button()
screen.blit(logo_image, logo_rect)
def search_and_display_report(screen, sheet, menu_width):
global s1_menu_button_rect
global menu_button_rect
global menu_open
menu_button_rect = pygame.Rect(screen.get_width() - 780, 20, 30, 30)
s1_menu_button_rect = pygame.Rect(screen.get_width() - 780, 20, 30, 3)
pygame.display.flip()
search_input = ""
search_active = True
menu_open = False
result_offset = 0 # Starting offset for results
scroll_position = 0
scroll_speed = 5
while search_active:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
search_active = False
elif event.key == pygame.K_BACKSPACE:
search_input = search_input[:-1]
else:
search_input += event.unicode
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # Left mouse button
if menu_button_rect.collidepoint(event.pos):
menu_open = not menu_open
screen.fill(BACKGROUND_COLOR)
draw_logo_and_header()
# Render search input box
search_input_rect = pygame.Rect(50, 140, 700, 50)
pygame.draw.rect(screen, INPUT_COLOR, search_input_rect)
search_input_text_surface = FONT.render(search_input, True, TEXT_COLOR)
screen.blit(search_input_text_surface, (search_input_rect.x + 10, search_input_rect.y + 10))
# Render search label text
search_label_text = FONT.render("Enter Name to Search:", True, TEXT_COLOR)
screen.blit(search_label_text, (50, 80))
# Display the search input box
search_input_rect = pygame.Rect(50, 140, 700, 50)
pygame.draw.rect(screen, INPUT_COLOR, search_input_rect)
# Apply mirroring to the search input and render it
mirrored_search_input = get_display(search_input)
search_input_text_surface = FONT.render(mirrored_search_input, True, TEXT_COLOR)
screen.blit(search_input_text_surface, (search_input_rect.x + 10, search_input_rect.y + 10))
cursor_logic()
menu_logic()
pygame.display.flip()
# Search for the entered name in the Excel file
matching_rows = []
for row in sheet.iter_rows(min_row=2, values_only=True):
if row[0] is not None and search_input.lower() in row[0].lower():
matching_rows.append(row)
screen.fill(BACKGROUND_COLOR)
if matching_rows:
# Render the matching speeches in search result style
result_y = 200
result_spacing = 20
result_rect_width = 700
result_rect_height = 100
for i, speech in enumerate(matching_rows):
result_rect = pygame.Rect(50, result_y, result_rect_width, result_rect_height)
pygame.draw.rect(screen, (245, 245, 245), result_rect)
pygame.draw.rect(screen, (200, 200, 200), result_rect, 2)
name_text = get_display(speech[0])
topic_text = get_display(speech[1])
name_surface = FONT.render(name_text, True, (68, 68, 68))
topic_surface = FONT.render(topic_text, True, (102, 102, 102))
screen.blit(name_surface, (result_rect.x + 20, result_rect.y + 20))
screen.blit(topic_surface, (result_rect.x + 20, result_rect.y + 50))
result_y += result_rect_height + result_spacing
displaying_results = True
result_offset = 0 # Initial offset for spacing
scroll_target_offset = result_offset
scroll_y = 0
current_page = 1
results_per_page = 3 # Update this to display 3 results per page
total_pages = (len(matching_rows) + results_per_page - 1) // results_per_page
# Main loop for displaying results
while displaying_results:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
displaying_results = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # Left mouse button
if menu_button_rect.collidepoint(event.pos):
menu_open = not menu_open
elif prev_page_rect.collidepoint(event.pos) and current_page > 1:
current_page -= 1
current_page = max(current_page, 1)
elif next_page_rect.collidepoint(event.pos) and current_page < total_pages:
current_page += 1
# Calculate which results to display on the current page
start_idx = (current_page - 1) * results_per_page
end_idx = min(start_idx + results_per_page, len(matching_rows))
# Clear the screen
screen.fill(BACKGROUND_COLOR)
# Render search results
if matching_rows:
result_y = 200
result_spacing = 20
result_rect_width = 700
result_rect_height = 100
for i, speech in enumerate(matching_rows[result_offset:result_offset + results_per_page]):
result_rect = pygame.Rect(50, result_y + scroll_y, result_rect_width, result_rect_height)
pygame.draw.rect(screen, (245, 245, 245), result_rect)
pygame.draw.rect(screen, (200, 200, 200), result_rect, 2)
name_text = get_display(speech[0])
topic_text = get_display(speech[1])
name_surface = FONT.render(name_text, True, (68, 68, 68))
topic_surface = FONT.render(topic_text, True, (102, 102, 102))
screen.blit(name_surface, (result_rect.x + 20, result_rect.y + 20))
screen.blit(topic_surface, (result_rect.x + 20, result_rect.y + 50))
result_y += result_rect_height + result_spacing
draw_logo_and_header() # Draw the logo and header
# Render pagination buttons with arrow symbols
prev_page_text = FONT2.render("←", True, (68, 68, 68)) # Left arrow symbol
next_page_text = FONT2.render("→", True, (68, 68, 68)) # Right arrow symbol
prev_page_rect = prev_page_text.get_rect(right=screen.get_width() - 70, y=screen.get_height() - 70)
next_page_rect = next_page_text.get_rect(right=screen.get_width() - 20, y=screen.get_height() - 70)
screen.blit(prev_page_text, prev_page_rect)
screen.blit(next_page_text,next_page_rect)
# Display the page count
page_count_text = FONT.render(f"{current_page} out of {total_pages}", True, (68, 68, 68))
page_count_rect = page_count_text.get_rect(center=(screen.get_width() // 2, screen.get_height() - 50))
screen.blit(page_count_text, page_count_rect)
# Draw the menu if open
menu_logic()
pygame.display.flip()
pygame.display.flip()
while running:
screen.fill(BACKGROUND_COLOR)
# Draw the logo and header
pygame.draw.rect(screen, (255, 255, 255), (0, 0, screen.get_width(), 70))
draw_menu_button()
screen.blit(logo_image, logo_rect)
# Update mouse coordinates
mouse_x, mouse_y = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
if active_input == "name":
active_input = "topic"
elif active_input == "topic":
active_input = "phone"
elif active_input == "phone":
active_input = "date" # Activate the date input
else:
# Handle adding the speech details and saving to Excel
new_row = [input_name, input_topic, input_phone, input_date]
sheet.append(new_row)
with open(occupied_dates_file, 'a') as f:
f.write(str(input_date) + '\n')
workbook.save(file_path)
print("Data saved to Excel.")
# Retrieve all rows and convert them into a list of dictionaries
all_rows = list(sheet.iter_rows(min_row=2, values_only=True))
sorted_rows = sorted(all_rows, key=itemgetter(3)) # Sort based on the date column (0-indexed)
# Clear existing data in the sheet (except headers)
sheet.delete_rows(2, sheet.max_row)
# Write sorted rows back to the sheet
for row in sorted_rows:
sheet.append(row)
# Save the workbook after sorting
workbook.save(file_path)
if is_hebrew(input_name):
input_name = input_name[::-1]
if is_hebrew(input_topic):
input_topic = input_topic[::-1]
# Generate report for the newly added speech data
report_text = [
f"Speech Details:",
f"Name: {get_display(input_name)}",
f"Topic: {get_display(input_topic)}",
f"Phone: {get_display(input_phone)}",
f"Date: {get_display(input_date)}",
"",
f"Report generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" # Include time
]
# Render report text
report_surfaces = [FONT.render(get_display(line), True, TEXT_COLOR) for line in report_text]
max_width = max(surface.get_width() for surface in report_surfaces)
report_height = sum(surface.get_height() for surface in report_surfaces) + 20
report_x = (screen.get_width() - max_width) // 2
report_y = (screen.get_height() - report_height) // 2
pygame.draw.rect(screen, INPUT_COLOR, (report_x - 10, report_y - 10, max_width + 20, report_height))
for surface in report_surfaces:
screen.blit(surface, (report_x, report_y))
report_y += surface.get_height()
pygame.display.flip()
pygame.time.wait(5000)
input_name = ""
input_topic = ""
input_phone = ""
input_date = ""
active_input = "name"
elif event.key == pygame.K_BACKSPACE:
if active_input == "name":
input_name = input_name[:-1]
elif active_input == "topic":
input_topic = input_topic[:-1]
elif active_input == "phone":
input_phone = input_phone[:-1]
elif active_input == "date":
input_date = input_date[:-1]
else:
if active_input == "name":
input_name += event.unicode
elif active_input == "topic":
input_topic += event.unicode
elif active_input == "phone":
input_phone += event.unicode
elif active_input == "date":
input_date += event.unicode
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # Left mouse button
if menu_button_rect.collidepoint(event.pos):
menu_open = not menu_open
if event.button == 1: # Left mouse button
if search_button_rect.collidepoint(event.pos):
search_open = not search_open
input_labels = {
"name": "Orator's Name:",
"topic": "Speech Topic:",
"phone": "Phone Number:",
"date": "Speech Date (YYYY-MM-DD):"
}
# Render input label text
input_label_text = FONT.render(input_labels[active_input], True, TEXT_COLOR)
# Display the input_text_surface based on the active input
if active_input == "date":
input_text = input_date
elif active_input == "name":
input_text = input_name
elif active_input == "topic":
input_text = input_topic
else:
input_text = input_phone
# Mirrored text using bidi algorithm
mirrored_input_text = get_display(input_text)
input_text_surface = FONT.render(mirrored_input_text, True, TEXT_COLOR)
input_rect = pygame.Rect(50, 140, 700, 50)
pygame.draw.rect(screen, INPUT_COLOR, input_rect)
screen.blit(input_text_surface, (input_rect.x + 10, input_rect.y + 10))
# Display the input_text_surface based on the active input
if active_input == "date":
if not input_date: # If no date is input, find next available Saturday
input_date = find_next_available_saturday(date.today()).strftime("%Y-%m-%d")
input_text_surface = FONT.render(input_date, True, TEXT_COLOR)
else:
mirrored_input_text = get_display(input_text) # Mirrored text using bidi algorithm
input_text_surface = FONT.render(mirrored_input_text, True, TEXT_COLOR)
input_rect = pygame.Rect(50, 140, 700, 50)
pygame.draw.rect(screen, INPUT_COLOR, input_rect)
screen.blit(input_text_surface, (input_rect.x + 10, input_rect.y + 10))
cursor_logic()
screen.blit(input_label_text, (50, 80))
menu_logic() # Show menu
if search_open and menu_open:
search_and_display_report(screen, sheet, menu_width)
search_button_sc(scroll_y)
pygame.display.flip()
pygame.quit()