Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 93 additions & 13 deletions app/calculadora.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import sys
import os
import platform
import math

import tkinter as tk
from tkinter import Menu, FALSE
Expand All @@ -32,7 +33,7 @@ class Calculadora(object):
4 | 5 | 6 | -
1 | 2 | 3 | +
. | 0 | = | /
| | ^ | √
log| % | ^ | √

OBS: É necessário importar o modulo style contido na pacote view,
e selecionar uma de suas classes de estilo.
Expand All @@ -44,6 +45,8 @@ def __init__(self, master):

self.settings = self._load_settings()

self.history = []

# Define estilo padrão para macOS, caso seja o sistema operacional utilizado
if platform.system() == 'Darwin':
self.theme = self._get_theme('Default Theme For MacOS')
Expand Down Expand Up @@ -119,7 +122,13 @@ def _create_menu(self, master):

config.add_separator()
config.add_command(label='Sair', command=self._exit)


#Adicionar histórico
history_menu = Menu(calc_menu)
calc_menu.add_cascade(label='Histórico', menu=history_menu)
history_menu.add_command(label='Mostrar Histórico', command=self._show_history)
history_menu.add_command(label='Limpar Histórico', command=self._clear_history)

def _change_theme_to(self, name='Dark'):
self.settings['current_theme'] = name

Expand All @@ -128,6 +137,30 @@ def _change_theme_to(self, name='Dark'):

self._realod_app()

def _show_history(self):
#Método para definir a configuração do histórico de operações
history_window = tk.Toplevel(self.master)
history_window.title("Histórico de cálculos")
history_window.configure(bg=self.theme['frame_bg'])
#Dimensões da window
window_width = 400
window_height = 300
screen_width = history_window.winfo_screenwidth()
screen_height = history_window.winfo_screenheight()
x_coordinate = (screen_width - window_width) // 2
y_coordinate = (screen_height - window_height) // 2
geometry_string = f"{window_width}x{window_height}+{x_coordinate}+{y_coordinate}"
history_window.geometry(geometry_string)

for i, entry in enumerate(self.history[-10:]):
label = tk.Label(history_window, text=f"{i+1}. {entry['operation']} = {entry['result']}", bg=self.theme['master_bg'], justify='left')
label.pack(anchor='w')

def _clear_history(self):
# Limpar o histórico
self.history.clear()


def _create_buttons(self, master):
""""Metódo responsável pela criação de todos os botões da calculadora,
indo desde adição de eventos em cada botão à distribuição no layout grid.
Expand Down Expand Up @@ -157,6 +190,8 @@ def _create_buttons(self, master):
self._BTN_MULT = tk.Button(master, text='*', cnf=self.theme['BTN_OPERADOR'])
self._BTN_EXP = tk.Button(master, text='^', cnf=self.theme['BTN_OPERADOR'])
self._BTN_RAIZ = tk.Button(master, text='√', cnf=self.theme['BTN_OPERADOR'])
self._BTN_LOG = tk.Button(master, text='log', cnf=self.theme['BTN_OPERADOR'])
self._BTN_PERCENT = tk.Button(master, text='%', cnf=self.theme['BTN_OPERADOR'])

# Seta configurações globais (width, height font etc) no botão especificado.
self.theme['BTN_DEFAULT'].update(self.settings['global'])
Expand All @@ -168,11 +203,7 @@ def _create_buttons(self, master):
self._BTN_CLEAR = tk.Button(master, text='C', cnf=self.theme['BTN_DEFAULT'])
self._BTN_DEL = tk.Button(master, text='<', cnf=self.theme['BTN_CLEAR'])
self._BTN_RESULT = tk.Button(master, text='=', cnf=self.theme['BTN_OPERADOR'])
self._BTN_DOT = tk.Button(master, text='.', cnf=self.theme['BTN_DEFAULT'])

# Instânciação dos botões vazios, para futura implementação
self._BTN_VAZIO1 = tk.Button(master, text='', cnf=self.theme['BTN_OPERADOR'])
self._BTN_VAZIO2 = tk.Button(master, text='', cnf=self.theme['BTN_OPERADOR'])
self._BTN_DOT = tk.Button(master, text='.', cnf=self.theme['BTN_DEFAULT'])

# Distribuição dos botões em um gerenciador de layout grid
# Linha 0
Expand Down Expand Up @@ -206,8 +237,8 @@ def _create_buttons(self, master):
self._BTN_DIV.grid(row=4, column=3, padx=1, pady=1)

# Linha 5
self._BTN_VAZIO1.grid(row=5, column=0, padx=1, pady=1)
self._BTN_VAZIO2.grid(row=5, column=1, padx=1, pady=1)
self._BTN_LOG.grid(row=5, column=0, padx=1, pady=1)
self._BTN_PERCENT.grid(row=5, column=1, padx=1, pady=1)
self._BTN_EXP.grid(row=5, column=2, padx=1, pady=1)
self._BTN_RAIZ.grid(row=5, column=3, padx=1, pady=1)

Expand All @@ -231,6 +262,8 @@ def _create_buttons(self, master):
self._BTN_EXP['command'] = partial(self._set_operator_in_input, '**')
self._BTN_RAIZ['command'] = partial(self._set_operator_in_input, '**(1/2)')

self._BTN_LOG['command'] = partial(self._set_operator_in_input, 'log(')
self._BTN_PERCENT['command'] = partial(self._set_operator_in_input, '%')

# Eventos dos botões de funcionalidades da calculadora
self._BTN_DOT['command'] = partial(self._set_dot_in_input, '.')
Expand Down Expand Up @@ -300,22 +333,69 @@ def _set_operator_in_input(self, operator):
"""Metódo responsável por captar o operador matemático clicado e setar no input"""
if self._entrada.get() == 'Erro':
return

if operator == 'log(':
# substitua a entrada padrão '0' por 'log('
if self._entrada.get() == '0':
self._entrada.delete(0, tk.END)
self._entrada.insert(0, 'log(')
else:
last_char = self._entrada.get()[-1] if self._entrada.get() else ''
if last_char in '+-/*)':
self._entrada.insert(len(self._entrada.get()), operator)
return

if self._entrada.get() == '':
# print('\33[91mOperação inválida.\33[m')
return
# Evita casos de operadores repetidos sequêncialmente, para evitar erros
if self._entrada.get()[-1] not in '+-*/' and self._lenght_max(self._entrada.get()):
self._entrada.insert(len(self._entrada.get()) ,operator)

def _get_data_in_input(self):
"""Pega os dados com todas as operações contidos dentro do input
para realizar o calculo"""
if self._entrada.get() == 'Erro':
return

result = self.calc.calculation(self._entrada.get())
self._set_result_in_input(result=result)
#cambiar en el issue de log este nombre de expression
expression = self._entrada.get()

if "log(" in expression:
# Encontre o índice da primeira ocorrência de "log("
log_index = expression.find("log(")
closing_index = expression.find(")", log_index)
if closing_index != -1:
# Extraia o argumento da função logaritmo
value_str = expression[log_index + 4 : closing_index]
try:
# Avalie o argumento do logaritmo e calcule o resultado
value = float(value_str)
log_result = math.log10(value)
# Substitua a expressão logarítmica pelo seu resultado na expressão
expression = (
expression[:log_index] +
str(log_result) +
expression[closing_index + 1:]
)
except (ValueError, ZeroDivisionError):
# Lidar com argumentos de logaritmo inválidos
self._set_result_in_input("Error")
#changement than ce bout de code
try:
result = eval(expression)
# Append the operation and its result to the history
self.history.append({'operation': expression, 'result': result})
self._set_result_in_input(result=result)
except (NameError, ZeroDivisionError, SyntaxError, ValueError):
self._set_result_in_input("Error")

def _process_expression(self, expression):
"""Processe a expressão contendo operações diferentes do logaritmo"""
try:
result = eval(expression)
self._set_result_in_input(result=result)
except (NameError, ZeroDivisionError, SyntaxError, ValueError):
self._set_result_in_input("Error")

def _set_result_in_input(self, result=0):
"""Seta o resultado de toda a operação dentro do input"""
Expand Down