예제 #1
0
class BalanceWidget(tkinter.Frame):
    # is a widget that tells the user the balance and the sum

    def __init__(self, parent, **optional_arguments):
        # initialized the frame and sub frames
        tkinter.Frame.__init__(self, parent)
        self.colors = None
        self.table_edit_listener: TableEditListener = None
        self.field_count = default_field_count
        self.expenditures_set = False

        # set up and process the optional arguments
        self.title_font = default_title_font
        self.head_font = default_table_head_font
        self.entry_font = default_entry_font
        self.title_text = default_title_text
        self.table_widget_name = None
        self.process_optional_arguments(optional_arguments)

        # sets up the title label
        self.head_label: tkinter.Label = None
        self.setup_title_label()

        # set up the edit button
        self.edit_button = None
        self.done_button = None
        self.setup_edit_button()

        # sets up the balance table
        self.balance_table: TableWidget = None
        self.setup_balance_table()
        self.balance_table.hide_config_buttons()

    def add_listener(self, listener):
        self.table_edit_listener = listener

    def process_optional_arguments(self, optional_arguments):
        # processes optional arguments passed to the Balance Widget
        # store the label fonts
        if 'title_font' in optional_arguments:
            self.title_font = optional_arguments['title_font']
        if 'head_font' in optional_arguments:
            self.head_font = optional_arguments['head_font']
        if 'entry_font' in optional_arguments:
            self.entry_font = optional_arguments['entry_font']
        # stores the name
        if 'name' in optional_arguments:
            self.title_text = optional_arguments['name']
            if self.title_text == "Initial Balance":
                self.table_widget_name = "initialBalances"
            elif self.title_text == "Current Balance":
                self.table_widget_name = "currentBalances"

    def setup_title_label(self):
        # adds a title label above the table
        self.head_label = tkinter.Label(self)
        self.head_label.config(text=self.title_text, font=self.title_font)
        self.head_label.grid(row=0, column=0, sticky="E")

    def setup_edit_button(self):
        self.edit_button = tkinter.Button(self, text="Edit", command=lambda: self.edit_pressed())
        self.done_button = tkinter.Button(self, text="Done", command=lambda: self.done_pressed())
        self.edit_button.grid(row=0, column=1, sticky="W")

    def edit_pressed(self):
        if self.expenditures_set:
            self.balance_table.show_config_buttons()
            self.edit_button.grid_forget()
            self.done_button.grid(row=0, column=1, sticky="W")

    def done_pressed(self):
        self.balance_table.hide_config_buttons()
        self.done_button.grid_forget()
        self.edit_button.grid(row=0, column=1, sticky="W")

    def send_edit_to_database(self, table_name: str, row_index: int, values):
        # passes the row values to the listener to the DatabaseModel to be processed and stored in the database
        value_dict = {'amount': TableWidget.unformat_from_currency(values[1]), 'source': values[0]}
        self.table_edit_listener.send_edit_to_database(table_name, row_index, value_dict)

    def setup_balance_table(self):
        # invert_axis is True because the data will be added in cols
        self.balance_table = TableWidget(self, 2, self.field_count, table_name=self.table_widget_name,
                                         invert_axis=True, column_widths=default_field_col_widths,
                                         head_font=self.head_font, entry_font=self.entry_font,
                                         header_widths=default_header_widths)
        self.balance_table.add_listener(self)
        self.balance_table.set_header_values(['Source', 'Amount'])
        self.balance_table.grid(row=1, columnspan=2)

    def set_balances(self, balance_matrix: [[]]):
        # sets the values in the balances table given the balance matrix
        table = []
        for row_index in range(len(balance_matrix)):
            values = [balance_matrix[row_index][1],
                      TableWidget.format_as_currency(balance_matrix[row_index][2])]
            table.append(values)
        self.balance_table.load_table_data(table)
        self.expenditures_set = True

    def set_colors(self, color_dict: {str: str}):
        self.colors = color_dict
        self.update_colors()

    def update_colors(self):
        if self.colors is not None:
            self.config(bg=self.colors['bg_col'])
            self.head_label.config(bg=self.colors['bg_col'], fg=self.colors['text_col'])
            self.balance_table.set_colors(self.colors)
            self.edit_button.config(fg=self.colors['button_col']['button_text_col'],
                                    highlightbackground=self.colors['button_col']['button_bg_col'],
                                    activeforeground=self.colors['button_col']['button_pressed_text'],
                                    activebackground=self.colors['button_col']['button_pressed_bg'])
            self.done_button.config(fg=self.colors['button_col']['button_text_col'],
                                    highlightbackground=self.colors['button_col']['button_bg_col'],
                                    activeforeground=self.colors['button_col']['button_pressed_text'],
                                    activebackground=self.colors['button_col']['button_pressed_bg'])
예제 #2
0
class ExpenditureWidget(tkinter.Frame, TableEditListener):
    # is a widget that displays the expenditures in the database

    def __init__(self, parent, **optional_arguments):
        # initializes the frame and sub frames
        tkinter.Frame.__init__(self, parent)
        self.colors = None
        self.expenditures_set = False
        self.table_edit_listener: TableEditListener = None
        self.field_count = default_field_count

        # setup the default parameters then process the optional arguments
        self.title_font = default_title_font
        self.head_font = default_table_head_font
        self.entry_font = default_entry_font
        self.title_text = default_title_text
        self.process_optional_arguments(optional_arguments)

        # setup the title label
        self.head_label = None
        self.setup_title_label()

        # setup the edit button
        self.edit_button = None
        self.done_button = None
        self.setup_edit_button()

        # setup the expenditure table
        self.expenditure_table = None
        self.setup_expenditure_table()

    def add_listener(self, listener: TableEditListener):
        self.table_edit_listener = listener

    def process_optional_arguments(self, optional_arguments):
        # processes the optional arguments passed to the constructor
        if 'title_font' in optional_arguments:
            self.title_font = optional_arguments['title_font']
        if 'head_font' in optional_arguments:
            self.head_font = optional_arguments['head_font']
        if 'entry_font' in optional_arguments:
            self.entry_font = optional_arguments['entry_font']
        if 'name' in optional_arguments:
            self.title_text = optional_arguments['name']

    def setup_title_label(self):
        # adds a title label above the table
        self.head_label = tkinter.Label(self)
        self.head_label.config(text=self.title_text, font=self.title_font)
        self.head_label.grid(row=0, column=0, sticky="E")

    def setup_expenditure_table(self):
        # adds the expenditure table
        self.expenditure_table = TableWidget(
            self,
            3,
            self.field_count + 1,
            table_name="expenditures",
            invert_axis=False,
            column_widths=default_field_col_widths,
            head_font=self.head_font,
            entry_font=self.entry_font)
        self.expenditure_table.hide_config_buttons()
        self.expenditure_table.add_listener(self)
        self.expenditure_table.set_header_values(['Amount', 'Name', 'Type'])
        self.expenditure_table.grid(row=1, columnspan=2)

    def setup_edit_button(self):
        self.edit_button = tkinter.Button(self,
                                          text="Edit",
                                          command=lambda: self.edit_pressed())
        self.done_button = tkinter.Button(self,
                                          text="Done",
                                          command=lambda: self.done_pressed())
        self.edit_button.grid(row=0, column=1, sticky="W")

    def edit_pressed(self):
        if self.expenditures_set:
            self.expenditure_table.show_config_buttons()
            self.edit_button.grid_forget()
            self.done_button.grid(row=0, column=1, sticky="W")

    def done_pressed(self):
        self.expenditure_table.hide_config_buttons()
        self.done_button.grid_forget()
        self.edit_button.grid(row=0, column=1, sticky="W")

    def set_expenditures(self, expenditure_matrix: [[]]):
        # passes the label values to the table to be inserted into the labels
        self.expenditures_set = True
        table = []
        for row_index in range(len(expenditure_matrix)):
            values = [
                TableWidget.format_as_currency(
                    expenditure_matrix[row_index][1]),
                expenditure_matrix[row_index][2],
                expenditure_matrix[row_index][3]
            ]
            table.append(values)
        self.expenditure_table.load_table_data(table)

    def send_edit_to_database(self, table_name: str, row_index: int, values):
        # passes the row values to the listener to the DatabaseModel to be processed and stored in the database
        value_dict = {
            'amount': TableWidget.unformat_from_currency(values[0]),
            'name': values[1],
            'type': values[2]
        }
        self.table_edit_listener.send_edit_to_database(table_name, row_index,
                                                       value_dict)

    def set_colors(self, color_dict: {str: str}):
        self.colors = color_dict
        self.update_colors()

    def update_colors(self):
        if self.colors is not None:
            self.config(bg=self.colors['bg_col'])
            self.head_label.config(bg=self.colors['bg_col'],
                                   fg=self.colors['text_col'])
            self.expenditure_table.set_colors(self.colors)
            self.edit_button.config(
                fg=self.colors['button_col']['button_text_col'],
                highlightbackground=self.colors['button_col']['button_bg_col'],
                activeforeground=self.colors['button_col']
                ['button_pressed_text'],
                activebackground=self.colors['button_col']
                ['button_pressed_bg'])
            self.done_button.config(
                fg=self.colors['button_col']['button_text_col'],
                highlightbackground=self.colors['button_col']['button_bg_col'],
                activeforeground=self.colors['button_col']
                ['button_pressed_text'],
                activebackground=self.colors['button_col']
                ['button_pressed_bg'])
예제 #3
0
class DataVisualizer(tkinter.LabelFrame):
    def __init__(self, parent, **optional_arguments):
        tkinter.LabelFrame.__init__(self,
                                    parent,
                                    text=optional_arguments['text'])
        self.colors = None

        # setup default parameters and then process optional arguments
        self.field_count = default_field_count
        self.process_optional_arguments(optional_arguments)

        # setup the table showing initial balance, current balance, and expenditure totals
        self.totals_table: TableWidget = None
        self.load_total_amounts()

        # sets up a separator between the two tables
        separator = Separator(self)
        separator.grid(row=0, column=1, sticky="NS")

        # setup the table showing spending by category
        self.category_table: TableWidget = None
        self.load_spending_by_category()

        # setup the pie chart
        self.pie_chart = PieChart(self)
        self.pie_chart.grid(row=1, columnspan=3)

        self.load_table_data(None, None, None)

    def process_optional_arguments(self, optional_arguments):
        if 'field_count' in optional_arguments.keys():
            self.field_count = optional_arguments['field_count']

    def load_spending_by_category(self):
        self.category_table = TableWidget(self,
                                          2,
                                          self.field_count,
                                          head_font=default_table_head_font,
                                          entry_font=default_entry_font,
                                          entry_justify_list=["right", "left"],
                                          head_justify_list=["right", "left"])
        self.category_table.hide_config_buttons()
        self.category_table.set_header_values(['Category', 'Amount'])
        self.category_table.grid(row=0, column=2)

    def load_total_amounts(self):
        self.totals_table = TableWidget(
            self,
            3,
            1,
            entry_font=default_entry_font,
            entry_justify=["left"],
            head_justify_list=["right", "right", "right"],
            invert_axis=True)
        self.totals_table.hide_config_buttons()
        self.totals_table.set_header_values(
            ["Initial Total", "Expenditure Total", "Current Total"])
        self.totals_table.grid(row=0, column=0)

    def load_table_data(self, expenditures_by_type: [[]], initial_balances,
                        current_balances):
        self.load_expenditure_data(expenditures_by_type)
        self.load_totals_data(initial_balances, expenditures_by_type,
                              current_balances)
        self.update_colors()

    def load_expenditure_data(self, expenditures_by_type: [[]]):
        if expenditures_by_type is not None and expenditures_by_type != []:
            labels = []
            values = []
            table = []
            for row_index in range(len(expenditures_by_type)):
                labels.append(expenditures_by_type[row_index][0])
                values.append(expenditures_by_type[row_index][1])
                table.append([
                    expenditures_by_type[row_index][0],
                    TableWidget.format_as_currency(
                        expenditures_by_type[row_index][1])
                ])
            self.category_table.load_table_data(table)
            self.pie_chart.construct_pie_chart(
                labels, values, text_col=self.pie_chart.label_text_col)
        else:
            self.category_table.clear_labels()
            self.pie_chart.construct_empty_chart()

    def load_totals_data(self, initial_balances, expenditures_by_type,
                         current_balances):
        if expenditures_by_type is not None and expenditures_by_type != []:
            total_spending = 0
            for row in expenditures_by_type:
                total_spending += row[1]
            spending_text = TableWidget.format_as_currency(total_spending)
            self.totals_table.set_value(spending_text, 0, 1)
        else:
            self.totals_table.set_value("-", 0, 1)

        if initial_balances is not None and initial_balances != []:
            total_initial_balance = 0
            for balance in initial_balances:
                total_initial_balance += balance[2]
            initial_text = TableWidget.format_as_currency(
                total_initial_balance)
            self.totals_table.set_value(initial_text, 0, 0)
        else:
            self.totals_table.set_value("-", 0, 0)

        if current_balances is not None and current_balances != []:
            total_current_balance = 0
            for balance in current_balances:
                total_current_balance += balance[2]
            current_text = TableWidget.format_as_currency(
                total_current_balance)
            self.totals_table.set_value(current_text, 0, 2)
        else:
            self.totals_table.set_value("-", 0, 2)

    def set_colors(self, color_dict: {str: str}):
        self.colors = color_dict
        self.update_colors()

    def update_colors(self):
        if self.colors is not None:
            self.config(bg=self.colors['bg_col'], fg=self.colors['text_col'])
            self.pie_chart.set_colors(self.colors['pie_chart_colors'])
            self.category_table.set_colors(
                self.colors['category_table_colors'])
            self.totals_table.set_colors(self.colors['totals_table_colors'])