Esempio n. 1
0
class ExercisesAndWorkouts(QWidget):
  show_muscle_group_signal = pyqtSignal(str)

  def __init__(self):
    super().__init__()
    self.setStyleSheet("""
    QWidget{
      color:#c7c7c7;
      font-weight: bold;
    }
    QPushButton{
      background-color: rgba(0, 0, 0, 0);
      border: 1px solid;
      font-size: 18px;
      font-weight: bold;
      border-color: #808080;
      min-height: 28px;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
      border-color: #6C6C6C;
    }""")
    self.db_wrapper = DatabaseWrapper()
    self.table_name = "Workouts"
    self.db_wrapper.create_local_table(self.table_name)
    if self.db_wrapper.local_table_is_empty(self.table_name): self.db_wrapper.insert_default_values(self.table_name)
    self.fetched_my_workouts = json.loads(self.db_wrapper.fetch_local_column(self.table_name, "my_workouts"))
    self.create_panel()

  def create_panel(self):
    self.grid = QGridLayout()
    self.grid.addWidget(self.create_my_workouts(), 0, 0)
    self.grid.addWidget(self.create_muscle_groups(), 0, 1)
    self.setLayout(self.grid)

  def create_my_workouts(self):
    frame = QFrame()
    frame.setFrameStyle(QFrame.StyledPanel)
    
    layout = QVBoxLayout()

    self.workouts_layout = QVBoxLayout()
    self.workouts_layout.setAlignment(Qt.AlignTop)

    label_layout = QHBoxLayout()
    label_layout.setAlignment(Qt.AlignCenter)
    label = QLabel("My Workouts")
    label.setFont(QFont("Ariel", 18, weight=QFont.Bold))
    label_layout.addWidget(label)
    self.workouts_layout.addLayout(label_layout)

    if len(self.fetched_my_workouts.keys()) > 0:
      self.buttons = [None] * len(self.fetched_my_workouts.keys())
      
      for i, workout in enumerate(self.fetched_my_workouts.keys()):
        self.buttons[i] = QPushButton(workout)
        self.buttons[i].setProperty("button_index", i)
        self.buttons[i].clicked.connect(partial(self.select_button, self.buttons[i].property("button_index")))
        self.workouts_layout.addWidget(self.buttons[i])
    
    buttons_layout = QHBoxLayout()
    create_new_workout_button = QPushButton("Create New Workout")
    create_new_workout_button.clicked.connect(lambda: self.create_new_workout())
    edit_workout_button = QPushButton("Edit Workout")
    edit_workout_button.clicked.connect(lambda: self.edit_workout())
    buttons_layout.addWidget(create_new_workout_button)
    buttons_layout.addWidget(edit_workout_button)
    
    layout.addLayout(self.workouts_layout)
    layout.addLayout(buttons_layout)
    frame.setLayout(layout)

    return frame
  
  def create_muscle_groups(self):
    frame = QFrame()
    frame.setFrameStyle(QFrame.StyledPanel)
    
    layout = QVBoxLayout()
    layout.setAlignment(Qt.AlignTop)    

    label_layout = QHBoxLayout()
    label = QLabel("Exercises by muscle group", self)
    label.setFont(QFont("Ariel", 15))
    label_layout.addWidget(label)
    
    grid_layout = QGridLayout()
    grid_layout.setAlignment(Qt.AlignCenter)

    chest_muscle_group = QVBoxLayout()
    chest_image = QPushButton(self)
    chest_image.setIcon(QIcon(muscle_groups["Chest"]))
    
    chest_image.setIconSize(QSize(100, 100))
    chest_image.resize(100, 100)
    chest_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    chest_image.setCursor(Qt.PointingHandCursor)
    chest_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Chest"))

    chest_label = QLabel("Chest", self)
    chest_label.setAlignment(Qt.AlignCenter)
    chest_muscle_group.addWidget(chest_image)
    chest_muscle_group.addWidget(chest_label)
    
    back_muscle_group = QVBoxLayout()
    back_image = QPushButton(self)
    back_image.setIcon(QIcon(muscle_groups["Back"]))
    back_image.setIconSize(QSize(100, 100))
    back_image.resize(100, 100)
    back_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    back_image.setCursor(Qt.PointingHandCursor)
    back_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Back"))
    
    back_label = QLabel("Back", self)
    back_label.setAlignment(Qt.AlignCenter)
    back_muscle_group.addWidget(back_image)
    back_muscle_group.addWidget(back_label)
    
    triceps_muscle_group = QVBoxLayout()
    triceps_image = QPushButton(self)
    triceps_image.setIcon(QIcon(muscle_groups["Triceps"]))
    triceps_image.setIconSize(QSize(100, 100))
    triceps_image.resize(100, 100)
    triceps_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    triceps_image.setCursor(Qt.PointingHandCursor)
    triceps_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Triceps"))

    triceps_label = QLabel("Triceps", self)
    triceps_label.setAlignment(Qt.AlignCenter)
    triceps_muscle_group.addWidget(triceps_image)
    triceps_muscle_group.addWidget(triceps_label) 
   
    biceps_muscle_group = QVBoxLayout()
    biceps_image = QPushButton(self)
    biceps_image.setIcon(QIcon(muscle_groups["Biceps"]))
    biceps_image.setIconSize(QSize(100, 100))
    biceps_image.resize(100, 100)
    biceps_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    biceps_image.setCursor(Qt.PointingHandCursor)
    biceps_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Biceps"))
    
    biceps_label = QLabel("Biceps", self)
    biceps_label.setAlignment(Qt.AlignCenter)
    biceps_muscle_group.addWidget(biceps_image)
    biceps_muscle_group.addWidget(biceps_label) 
    
    shoulders_muscle_group = QVBoxLayout()
    shoulders_image = QPushButton(self)
    shoulders_image.setIcon(QIcon(muscle_groups["Shoulders"]))
    shoulders_image.setIconSize(QSize(100, 100))
    shoulders_image.resize(100, 100)
    shoulders_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    shoulders_image.setCursor(Qt.PointingHandCursor)
    shoulders_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Shoulders"))
    
    shoulders_label = QLabel("Shoulders", self)
    shoulders_label.setAlignment(Qt.AlignCenter)
    shoulders_muscle_group.addWidget(shoulders_image)
    shoulders_muscle_group.addWidget(shoulders_label) 
    
    core_muscle_group = QVBoxLayout()
    core_image = QPushButton(self)
    core_image.setIcon(QIcon(muscle_groups["Core"]))
    core_image.setIconSize(QSize(100, 100))
    core_image.resize(100, 100)
    core_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    core_image.setCursor(Qt.PointingHandCursor)
    core_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Core"))

    core_label = QLabel("Core", self)
    core_label.setAlignment(Qt.AlignCenter)
    core_muscle_group.addWidget(core_image)
    core_muscle_group.addWidget(core_label)

    quadriceps_muscle_group = QVBoxLayout()
    quadriceps_image = QPushButton(self)
    quadriceps_image.setIcon(QIcon(muscle_groups["Quadriceps"]))
    quadriceps_image.setIconSize(QSize(100, 100))
    quadriceps_image.resize(100, 100)
    quadriceps_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    quadriceps_image.setCursor(Qt.PointingHandCursor)
    quadriceps_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Legs"))
    
    quadriceps_label = QLabel("Quadriceps", self)
    quadriceps_label.setAlignment(Qt.AlignCenter)
    quadriceps_muscle_group.addWidget(quadriceps_image)
    quadriceps_muscle_group.addWidget(quadriceps_label)

    calves_muscle_group = QVBoxLayout()
    calves_image = QPushButton(self)
    calves_image.setIcon(QIcon(muscle_groups["Calves"]))
    calves_image.setIconSize(QSize(100, 100))
    calves_image.resize(100, 100)
    calves_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    calves_image.setCursor(Qt.PointingHandCursor)
    calves_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Calves"))
    
    calves_label = QLabel("Calves", self)
    calves_label.setAlignment(Qt.AlignCenter)
    calves_muscle_group.addWidget(calves_image)
    calves_muscle_group.addWidget(calves_label)
    
    hamstrings_muscle_group = QVBoxLayout()
    hamstrings_image = QPushButton(self)
    hamstrings_image.setIcon(QIcon(muscle_groups["Hamstrings"]))
    hamstrings_image.setIconSize(QSize(100, 100))
    hamstrings_image.resize(100, 100)
    hamstrings_image.setStyleSheet("border: none; padding-left: 50%; background-color: white;")
    hamstrings_image.setCursor(Qt.PointingHandCursor)
    hamstrings_image.clicked.connect(lambda: self.show_muscle_group_signal.emit("Legs"))
    
    hamstrings_label = QLabel("Hamstrings", self)
    hamstrings_label.setAlignment(Qt.AlignCenter)
    hamstrings_muscle_group.addWidget(hamstrings_image)
    hamstrings_muscle_group.addWidget(hamstrings_label)

    grid_layout.addLayout(chest_muscle_group, 0, 0)
    grid_layout.addLayout(back_muscle_group, 0, 1)
    grid_layout.addLayout(triceps_muscle_group, 0, 2)
    grid_layout.addLayout(biceps_muscle_group, 1, 0)
    grid_layout.addLayout(shoulders_muscle_group, 1, 1)
    grid_layout.addLayout(core_muscle_group, 1, 2)
    grid_layout.addLayout(quadriceps_muscle_group, 2, 0)
    grid_layout.addLayout(calves_muscle_group, 2, 1)
    grid_layout.addLayout(hamstrings_muscle_group, 2, 2)

    layout.addLayout(label_layout) 
    layout.addWidget(QLabel(" "))
    layout.addLayout(grid_layout)
    frame.setLayout(layout) 

    return frame

  def create_new_workout(self):
    self.create_workout_window = CreateWorkoutWindow() 
    self.create_workout_window.refresh_after_creating_signal.connect(lambda signal: self.refresh_my_workouts_after_create(signal))
    self.create_workout_window.setGeometry(100, 200, 300, 300) 
    self.create_workout_window.show()

  def edit_workout(self):
    selected_button = None
    try:
      for button in self.buttons:
        if button.isFlat(): selected_button = button
      if selected_button != None:
        self.edit_workout_window = CreateWorkoutWindow(selected_button.text())
        self.edit_workout_window.refresh_my_workouts_signal.connect(lambda workout_name: self.refresh_my_workouts(workout_name))
        self.edit_workout_window.setGeometry(100, 200, 300, 300) 
        self.edit_workout_window.show()
    except AttributeError: # no workouts
      return

  def select_button(self, button_index):
    for button in self.buttons:
      if button.isFlat():
        button.setFlat(False)
        button.setStyleSheet("")
        button.setStyleSheet("""
        QPushButton{
          background-color: rgba(0, 0, 0, 0);
          border: 1px solid;
          font-size: 18px;
          font-weight: bold;
          border-color: #808080;
          min-height: 28px;
          white-space:nowrap;
          text-align: left;
          padding-left: 5%;
          font-family: Montserrat;
        }
        QPushButton:hover:!pressed{
          border: 2px solid;
          border-color: #747474;
        }
        QPushButton:pressed:{
          border: 2px solid;
          background-color: #323232;
          border-color: #6C6C6C;
        }""")

    self.buttons[button_index].setFlat(True)
    self.buttons[button_index].setStyleSheet("background-color: #323232; border-color: #6C6C6C; border: 2px solid;")
  
  @pyqtSlot(str)
  def refresh_my_workouts(self, workout_name): 
    for button in self.buttons:
      if button.text() == workout_name:
        button.setParent(None)

  @pyqtSlot(bool)
  def refresh_my_workouts_after_create(self, signal):
    if signal:
      self.fetched_my_workouts = json.loads(self.db_wrapper.fetch_local_column(self.table_name, "my_workouts"))
      for i in reversed(range(self.workouts_layout.count())):
        if self.workouts_layout.itemAt(i).widget() != None:
          self.workouts_layout.itemAt(i).widget().setParent(None)
      
      if len(self.fetched_my_workouts.keys()) > 0:
        self.buttons = [None] * len(self.fetched_my_workouts.keys())
        for i, workout in enumerate(self.fetched_my_workouts.keys()):
          self.buttons[i] = QPushButton(workout)
          self.buttons[i].setProperty("button_index", i)
          self.buttons[i].clicked.connect(partial(self.select_button, self.buttons[i].property("button_index")))
          self.workouts_layout.addWidget(self.buttons[i])
Esempio n. 2
0
class MainPanel(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.db_wrapper = DatabaseWrapper()
        self.table_name = "Compound Exercises"
        self.setStyleSheet("""
    QWidget{
      color:#c7c7c7;
      font-weight: bold;
    }
    QPushButton{
      background-color: rgba(0, 0, 0, 0);
      border: 1px solid;
      font-size: 18px;
      font-weight: bold;
      border-color: #808080;
      min-height: 28px;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
      border-color: #6C6C6C;
    }
    QComboBox{
      border-radius: 4px;
      font-size: 18px;
      font-weight: bold;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
      min-height: 28px;
      background-color: #440D0F;
    }
    QComboBox:down-arrow{
      width: 0px;
      height: 0px;
      background: #d3d3d3; 
      opacity:0
    }
    QComboBox:drop-down{
      background-color: #440D0F;
      border: 0px;
      opacity:0;
      border-radius: 0px;
      width: 0px;
      height: 0px;
    }
    QComboBox:hover:!pressed{
      background-color: #5D1A1D;
    }
    QComboBox:pressed{
      background-color: #551812;
    }
    """)
        self.current_year = str(datetime.now().year)
        self.db_wrapper.create_local_table(self.table_name)
        if self.db_wrapper.local_table_is_empty(self.table_name):
            self.db_wrapper.insert_default_values(self.table_name)

        self.units = "kg" if self.db_wrapper.fetch_local_column(
            "Users", "units") == "metric" else "lb"
        big_lifts_units = "kg" if self.db_wrapper.fetch_local_column(
            self.table_name, "units") == "metric" else "lb"

        one_rep_maxes = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "one_rep_maxes"))
        lifts_for_reps = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "lifts_for_reps"))
        self.rm_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name, "rm_history"))

        if not self.current_year in self.rm_history:
            self.add_year_to_rm_history(self.current_year)
            self.rm_history = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "rm_history"))

        if self.units != big_lifts_units:
            units_name = "metric" if self.units == "kg" else "imperial"
            self.db_wrapper.update_table_column(self.table_name, "units",
                                                units_name)
            if units_name == "metric":
                for exercise, weight in one_rep_maxes.items():
                    one_rep_maxes[exercise] = str(pounds_to_kg(weight))
                for exercise, reps_and_weight in lifts_for_reps.items():
                    lifts_for_reps[exercise] = [
                        reps_and_weight[0],
                        str(pounds_to_kg(reps_and_weight[1]))
                    ]

            elif units_name == "imperial":
                for exercise, weight in one_rep_maxes.items():
                    one_rep_maxes[exercise] = str(kg_to_pounds(weight))
                for exercise, reps_and_weight in lifts_for_reps.items():
                    lifts_for_reps[exercise] = [
                        reps_and_weight[0],
                        str(kg_to_pounds(reps_and_weight[1]))
                    ]

            for year in self.rm_history:
                for month in self.rm_history[year]:
                    for exercise_type in list(self.rm_history[year][month]):
                        for exercise in list(
                                self.rm_history[year][month][exercise_type]):
                            for i, weight in enumerate(
                                    self.rm_history[year][month][exercise_type]
                                [exercise]):
                                if units_name == "imperial":
                                    self.rm_history[year][month][
                                        exercise_type][exercise][i] = str(
                                            kg_to_pounds(weight))
                                elif units_name == "metric":
                                    self.rm_history[year][month][
                                        exercise_type][exercise][i] = str(
                                            pounds_to_kg(weight))

            self.db_wrapper.update_table_column(self.table_name,
                                                "one_rep_maxes", one_rep_maxes)
            self.db_wrapper.update_table_column(self.table_name,
                                                "lifts_for_reps",
                                                lifts_for_reps)
            self.convert_lift_history_weight(self.units)

        self.one_RM = [[lift, " ".join([weight, self.units])]
                       for lift, weight in one_rep_maxes.items()]
        self.lifts_reps = [[lift, " ".join(["x".join(weight), self.units])]
                           for lift, weight in lifts_for_reps.items()]

        self.lift_history_window = LiftHistory()
        self.lift_history_window.setGeometry(100, 200, 300, 300)

        self.plists_window = PreferredLifts()
        self.plists_window.change_lifts_signal.connect(
            self.changed_preferred_lifts)

        self.update_1RM_window = Update1RMWindow()
        self.update_1RM_window.change_1RM_lifts_signal.connect(
            self.changed_1RM_lifts)
        self.update_1RM_window.history_signal.connect(
            lambda signal: self.lift_history_window.create_history(signal))
        self.update_1RM_window.update_graph_signal.connect(
            lambda signal: self.refresh_graph(signal))

        self.lifts_for_reps = UpdateLiftsForRepsWindow()
        self.lifts_for_reps.change_lifts_for_reps_signal.connect(
            self.changed_lifts_for_reps)
        self.lifts_for_reps.history_signal.connect(
            lambda signal: self.lift_history_window.create_history(signal))

        self.preferred_lifts = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "preferred_lifts"))
        self.one_rep_maxes = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "one_rep_maxes"))
        self.create_panel()

    def create_panel(self):
        main_panel_grid = QGridLayout()
        main_panel_grid.addLayout(self.description(), 0, 0, 1, 1)
        main_panel_grid.addWidget(self.create_time_graph(), 1, 0, 4, 1)
        main_panel_grid.addLayout(self.create_bottom_layout(), 5, 0, 3, 1)
        main_panel_grid.addLayout(self.create_function_buttons(), 8, 0, 1, 1)
        self.setLayout(main_panel_grid)

    def description(self):
        panel_description = QVBoxLayout()
        desc_font = QFont("Montserrat", 12)
        description_label = QLabel(
            "Keep notes and track progress of your preferred big lifts here.",
            self)
        description_label.setFont(desc_font)
        description_label.setFixedHeight(20)
        panel_description.addWidget(description_label)
        return panel_description

    def create_time_graph(self):
        self.graph_layout = QVBoxLayout()

        graph = OneRMGraphCanvas("Horizontal Press", self.rm_history,
                                 self.current_year, self)

        combobox_layout = QHBoxLayout()
        self.lifts_combobox = QComboBox(self)
        self.lifts_combobox.addItems(list(self.preferred_lifts.values()))
        self.lifts_combobox.currentTextChanged.connect(
            lambda lift: self.change_exercise_graph(lift))

        self.change_year_combobox = QComboBox(self)
        self.change_year_combobox.addItems(list(self.rm_history.keys()))
        self.change_year_combobox.setCurrentText(self.current_year)
        self.change_year_combobox.currentTextChanged.connect(
            lambda year: self.change_graph_year(year))

        combobox_layout.addWidget(self.change_year_combobox)
        combobox_layout.addWidget(self.lifts_combobox)

        toolbar = NavigationToolbar(graph, self)
        toolbar.setStyleSheet("background-color: white;")

        self.graph_layout.addWidget(toolbar)
        self.graph_layout.addWidget(graph)
        self.graph_layout.addLayout(combobox_layout)

        framed_graph = QFrame(self)
        framed_graph.setFrameStyle(QFrame.Box)
        framed_graph.setLineWidth(3)
        framed_graph.setLayout(self.graph_layout)

        return framed_graph

    def create_bottom_layout(self):
        bottom_layout = QHBoxLayout()
        bottom_layout.addWidget(self.create_one_rep_max())
        bottom_layout.addWidget(self.create_lifts_for_reps())
        return bottom_layout

    def create_one_rep_max(self):
        orm_panel = QVBoxLayout()
        main_label = QLabel("One Rep Max")
        main_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        self.horizontal_press_label_ORM = QLabel(": ".join(self.one_RM[0]))
        self.horizontal_press_label_ORM.setFont(QFont("Ariel", 10))

        self.floor_pull_label_ORM = QLabel(": ".join(self.one_RM[1]))
        self.floor_pull_label_ORM.setFont(QFont("Ariel", 10))

        self.squat_label_ORM = QLabel(": ".join(self.one_RM[2]))
        self.squat_label_ORM.setFont(QFont("Ariel", 10))

        self.vertical_press_label_ORM = QLabel(": ".join(self.one_RM[3]))
        self.vertical_press_label_ORM.setFont(QFont("Ariel", 10))

        orm_buttons = QHBoxLayout()
        update_button = QPushButton("Update")
        update_button.clicked.connect(lambda: self.update_1RM_window.show())
        clear_button = QPushButton("Clear")
        clear_button.clicked.connect(lambda: self.clear_one_rep_maxes())
        orm_buttons.addWidget(update_button)
        orm_buttons.addWidget(clear_button)

        orm_panel.addWidget(main_label)
        orm_panel.addWidget(self.horizontal_press_label_ORM)
        orm_panel.addWidget(self.floor_pull_label_ORM)
        orm_panel.addWidget(self.squat_label_ORM)
        orm_panel.addWidget(self.vertical_press_label_ORM)
        orm_panel.addLayout(orm_buttons)

        orm_panel.setSpacing(5)
        framed_layout = QFrame()
        framed_layout.setObjectName("graphObj")
        framed_layout.setFrameStyle(QFrame.Box)
        framed_layout.setLineWidth(3)
        framed_layout.setStyleSheet("""#graphObj {color: #322d2d;}""")
        framed_layout.setLayout(orm_panel)

        return framed_layout

    def create_lifts_for_reps(self):
        reps_panel = QVBoxLayout()
        main_label = QLabel("Lifts For Reps")
        main_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        self.horizontal_press_label_reps = QLabel(": ".join(
            self.lifts_reps[0]))
        self.horizontal_press_label_reps.setFont(QFont("Ariel", 10))

        self.floor_pull_label_reps = QLabel(": ".join(self.lifts_reps[1]))
        self.floor_pull_label_reps.setFont(QFont("Ariel", 10))

        self.squat_label_reps = QLabel(": ".join(self.lifts_reps[2]))
        self.squat_label_reps.setFont(QFont("Ariel", 10))

        self.vertical_press_label_reps = QLabel(": ".join(self.lifts_reps[3]))
        self.vertical_press_label_reps.setFont(QFont("Ariel", 10))

        reps_buttons = QHBoxLayout()
        update_button = QPushButton("Update")
        update_button.clicked.connect(lambda: self.lifts_for_reps.show())
        clear_button = QPushButton("Clear")
        clear_button.clicked.connect(lambda: self.clear_lifts_for_reps())
        reps_buttons.addWidget(update_button)
        reps_buttons.addWidget(clear_button)

        reps_panel.addWidget(main_label)
        reps_panel.addWidget(self.horizontal_press_label_reps)
        reps_panel.addWidget(self.floor_pull_label_reps)
        reps_panel.addWidget(self.squat_label_reps)
        reps_panel.addWidget(self.vertical_press_label_reps)
        reps_panel.addLayout(reps_buttons)

        framed_layout = QFrame()
        framed_layout.setObjectName("graphObj")
        framed_layout.setFrameStyle(QFrame.Box)
        framed_layout.setLineWidth(3)
        framed_layout.setStyleSheet("""#graphObj {color: #322d2d;}""")
        framed_layout.setLayout(reps_panel)

        return framed_layout

    def create_function_buttons(self):
        buttons_panel = QHBoxLayout()
        lift_history_button = QPushButton()
        lift_history_button.setText("Lift History")
        lift_history_button.clicked.connect(
            lambda: self.lift_history_window.show())
        preferred_lists_button = QPushButton()
        preferred_lists_button.setText("Preferred Lifts")
        preferred_lists_button.clicked.connect(
            lambda: self.plists_window.show())

        buttons_panel.addWidget(lift_history_button)
        buttons_panel.addWidget(preferred_lists_button)
        return buttons_panel

    @pyqtSlot(bool)
    def changed_preferred_lifts(self, changed):
        if changed:
            self.preferred_lifts = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "preferred_lifts"))
            parsed_lifts = list(self.preferred_lifts.values())

            one_RM_labels = [
                self.horizontal_press_label_ORM, self.floor_pull_label_ORM,
                self.squat_label_ORM, self.vertical_press_label_ORM
            ]

            lifts_for_reps_labels = [
                self.horizontal_press_label_reps, self.floor_pull_label_reps,
                self.squat_label_reps, self.vertical_press_label_reps
            ]

            for i, label in enumerate(one_RM_labels):
                label_text = label.text().split(":")
                label_text[0] = parsed_lifts[i]
                label.setText(": ".join(label_text))

            for i, label in enumerate(lifts_for_reps_labels):
                label_text = label.text().split(":")
                label_text[0] = parsed_lifts[i]
                label.setText(": ".join(label_text))

            self.refresh_graph(True)

    @pyqtSlot(bool)
    def changed_1RM_lifts(self, changed):
        if changed:
            fetch_weight = list(
                json.loads(
                    self.db_wrapper.fetch_local_column(
                        self.table_name, "one_rep_maxes")).values())
            self.set_1RM_labels_text(fetch_weight)

    @pyqtSlot(bool)
    def changed_lifts_for_reps(self, changed):
        if changed:
            fetch_reps_and_weight = list(
                json.loads(
                    self.db_wrapper.fetch_local_column(
                        self.table_name, "lifts_for_reps")).values())
            self.set_lifts_for_reps_labels_text(fetch_reps_and_weight)

    def set_lifts_for_reps_labels_text(self, text):
        lifts_for_reps_labels = [
            self.horizontal_press_label_reps, self.floor_pull_label_reps,
            self.squat_label_reps, self.vertical_press_label_reps
        ]

        for i, label in enumerate(lifts_for_reps_labels):
            label_text = label.text().split(": ")
            label_text[1] = " ".join(["x".join(text[i]), self.units])
            label.setText(": ".join(label_text))

    def set_1RM_labels_text(self, text):
        one_RM_labels = [
            self.horizontal_press_label_ORM, self.floor_pull_label_ORM,
            self.squat_label_ORM, self.vertical_press_label_ORM
        ]
        for i, label in enumerate(one_RM_labels):
            label_text = label.text().split(": ")
            label_text[1] = " ".join([text[i], self.units])
            label.setText(": ".join(label_text))

    def clear_one_rep_maxes(self):
        for exercise, value in self.one_rep_maxes.items():
            self.one_rep_maxes[exercise] = "0"
        self.db_wrapper.update_table_column(self.table_name, "one_rep_maxes",
                                            self.one_rep_maxes)
        self.set_1RM_labels_text(list(self.one_rep_maxes.values()))
        self.update_1RM_window.set_line_edit_values()

    def clear_lifts_for_reps(self):
        lifts_for_reps = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "lifts_for_reps"))
        for exercise in lifts_for_reps:
            lifts_for_reps[exercise] = ["0", "0"]
        self.db_wrapper.update_table_column(self.table_name, "lifts_for_reps",
                                            lifts_for_reps)
        self.set_lifts_for_reps_labels_text(list(lifts_for_reps.values()))
        self.lifts_for_reps.set_line_edit_values()

    def replace_graph(self, lift_type):
        new_graph = OneRMGraphCanvas(lift_type, self.rm_history,
                                     self.current_year, self)
        new_toolbar = NavigationToolbar(new_graph, self)
        new_toolbar.setStyleSheet("background-color: white;")

        old_toolbar_reference = self.graph_layout.itemAt(0).widget()
        old_graph_reference = self.graph_layout.itemAt(1).widget()

        self.graph_layout.replaceWidget(old_toolbar_reference, new_toolbar)
        self.graph_layout.replaceWidget(old_graph_reference, new_graph)

        old_toolbar_reference.deleteLater()
        old_graph_reference.deleteLater()

    def change_exercise_graph(self, exercise_name):
        lift_type = None
        for l_type, exercise in self.preferred_lifts.items():
            if exercise == exercise_name: lift_type = l_type
        self.replace_graph(lift_type)

    def change_graph_year(self, year):
        self.current_year = year
        lift_type = None
        for l_type, exercise in self.preferred_lifts.items():
            if exercise == str(self.lifts_combobox.currentText()):
                lift_type = l_type
        self.replace_graph(lift_type)
        self.change_year_combobox.setCurrentText(self.current_year)

    @pyqtSlot(bool)
    def refresh_graph(self, signal):
        if signal:
            self.rm_history = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "rm_history"))
            lift_type = None
            for l_type, exercise in self.preferred_lifts.items():
                if exercise == str(self.lifts_combobox.currentText()):
                    lift_type = l_type
            self.replace_graph(lift_type)

    def convert_lift_history_weight(self, convert_to_units):
        try:
            lift_history = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "lift_history"))
        except TypeError:  # lift history is empty
            return
        if convert_to_units == "kg":
            for lift in lift_history:
                if isinstance(
                        lift[1], list
                ):  # second element of history entry is list, it is lifts_for_reps entry
                    lift[1][1] = str(pounds_to_kg(float(lift[1][1])))
                else:
                    lift[1] = str(pounds_to_kg(float(lift[1])))
        elif convert_to_units == "lb":
            for lift in lift_history:
                if isinstance(lift[1], list):
                    lift[1][1] = str(kg_to_pounds(float(lift[1][1])))
                else:
                    lift[1] = str(kg_to_pounds(float(lift[1])))
        lift_history = json.dumps(lift_history)
        self.db_wrapper.update_table_column(self.table_name,
                                            "lift_history",
                                            lift_history,
                                            convert_lift_history_units=True)

    def add_year_to_rm_history(self, year):
        new_year = {}
        for month in self.db_wrapper.months:
            exercises_dict = {}
            for lift_type in self.preferred_lifts:
                exercises_dict[lift_type] = {
                    self.preferred_lifts[lift_type]: []
                }
            new_year[month] = exercises_dict
        self.rm_history[str(year)] = new_year
        self.rm_history = json.dumps(self.rm_history)
        self.db_wrapper.update_table_column(self.table_name, "rm_history",
                                            self.rm_history)
Esempio n. 3
0
class MainPanel(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.db_wrapper = DatabaseWrapper()
        self.table_name = "Weight Loss"
        self.setStyleSheet("""
    QWidget{
      color:#c7c7c7;
      font-weight: bold;
    }
    QPushButton{
      background-color: rgba(0, 0, 0, 0);
      border: 1px solid;
      font-size: 18px;
      font-weight: bold;
      border-color: #808080;
      min-height: 28px;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
      border-color: #6C6C6C;
    }
    QComboBox{
      border-radius: 4px;
      font-size: 18px;
      font-weight: bold;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
      min-height: 28px;
      background-color: #440D0F;
    }
    QComboBox:down-arrow{
      width: 0px;
      height: 0px;
      background: #d3d3d3; 
      opacity:0
    }
    QComboBox:drop-down{
      background-color: #440D0F;
      border: 0px;
      opacity:0;
      border-radius: 0px;
      width: 0px;
      height: 0px;
    }
    QComboBox:hover:!pressed{
      background-color: #5D1A1D;
    }
    QComboBox:pressed{
      background-color: #551812;
    }
    """)

        self.db_wrapper.create_local_table(self.table_name)
        self.db_wrapper.create_local_table("Nutrition")

        if self.db_wrapper.local_table_is_empty("Nutrition"):
            self.db_wrapper.insert_default_values("Nutrition")

        if self.db_wrapper.local_table_is_empty(self.table_name):
            self.db_wrapper.insert_default_values(self.table_name)

        self.fetch_user_data()
        self.date = datetime.today().strftime("%d/%m/%Y")
        self.current_year = datetime.today().year
        self.calorie_goal = self.db_wrapper.fetch_local_column(
            "Nutrition", "calorie_goal")

        self.units = "kg" if self.db_wrapper.fetch_local_column(
            "Users", "units") == "metric" else "lb"
        weight_loss_units = "kg" if self.db_wrapper.fetch_local_column(
            self.table_name, "units") == "metric" else "lb"
        self.weight_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "weight_history"))

        if self.units != weight_loss_units:
            units_name = "metric" if self.units == "kg" else "imperial"
            self.db_wrapper.update_table_column(self.table_name, "units",
                                                units_name)
            if units_name == "metric":
                for date in self.weight_history:
                    self.weight_history[date] = str(
                        pounds_to_kg(self.weight_history[date]))

            elif units_name == "imperial":
                for date in self.weight_history:
                    self.weight_history[date] = str(
                        kg_to_pounds(self.weight_history[date]))

            self.db_wrapper.update_table_column(
                self.table_name, "weight_history",
                json.dumps(self.weight_history))

        self.preferred_activity = self.db_wrapper.fetch_local_column(
            self.table_name, "preferred_activity")
        self.cardio_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "cardio_history"))
        if not self.date in self.cardio_history:
            self.add_date_to_cardio_history()
        if not self.date in self.weight_history:
            self.add_date_to_weight_history()

        self.init_cardio_labels()
        self.create_panel()

    def create_panel(self):
        grid = QGridLayout()
        grid.addLayout(self.create_description(), 0, 0, 1, 1)
        grid.addWidget(self.create_graph(), 1, 0, 4, 1)
        grid.addLayout(self.create_bottom_layout(), 5, 0, 3, 1)
        self.setLayout(grid)

    def create_description(self):
        description = QVBoxLayout()
        description_font = QFont("Montserrat", 12)
        description_label = QLabel(
            "Keep notes and track your weight loss journey.", self)
        description_label.setFont(description_font)
        description_label.setFixedHeight(20)
        description.addWidget(description_label)
        return description

    def create_graph(self):
        self.graph_layout = QVBoxLayout()

        graph = WeightLossGraphCanvas(
            self.db_wrapper.months[datetime.today().month - 1],
            self.current_year, self)
        toolbar = NavigationToolbar(graph, self)
        toolbar.setStyleSheet("background-color: white;")

        combobox_layout = QHBoxLayout()
        self.months_combobox = QComboBox()

        months = []
        for entry in self.weight_history:
            month = entry.split("/")[1]
            for month_name, code in self.db_wrapper.months_mappings.items():
                if code == month: month = month_name
            if not month in months:
                months.append(month)
        if len(months) == 0:
            months.append(self.db_wrapper.months[datetime.today().month - 1])
        self.months_combobox.addItems(months)
        self.months_combobox.setCurrentText(
            self.db_wrapper.months[datetime.today().month - 1])
        self.months_combobox.currentTextChanged.connect(
            lambda month: self.change_month_graph(month))

        self.change_year_combobox = QComboBox()

        years = []
        for entry in self.weight_history:
            if not entry.split("/")[-1] in years:
                years.append(entry.split("/")[-1])
        if len(years) == 0: years.append(str(self.current_year))
        self.change_year_combobox.addItems(list(reversed(years)))
        self.change_year_combobox.currentTextChanged.connect(
            lambda year: self.change_year_graph(year))

        combobox_layout.addWidget(self.months_combobox)
        combobox_layout.addWidget(self.change_year_combobox)

        self.graph_layout.addWidget(toolbar)
        self.graph_layout.addWidget(graph)
        self.graph_layout.addLayout(combobox_layout)

        framed_graph = QFrame(self)
        framed_graph.setFrameStyle(QFrame.Box)
        framed_graph.setLineWidth(3)
        framed_graph.setLayout(self.graph_layout)

        return framed_graph

    def create_bottom_layout(self):
        bottom_layout = QHBoxLayout()
        bottom_layout.addWidget(self.create_weight_loss())
        bottom_layout.addWidget(self.create_cardio_notes())
        return bottom_layout

    def create_weight_loss(self):
        weight_loss = QVBoxLayout()
        main_label = QLabel("Weight Loss")
        main_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        current_weight_layout = QHBoxLayout()
        self.current_weight_label = QLabel(" ".join(
            ["Current Weight:", self.current_weight, self.units]))
        update_current_weight_button = QPushButton("Update")
        update_current_weight_button.clicked.connect(
            lambda: self.update_value("Current Weight", self.current_weight))
        current_weight_layout.addWidget(self.current_weight_label)
        current_weight_layout.addWidget(update_current_weight_button)

        weight_goal_layout = QHBoxLayout()
        self.weight_goal_label = QLabel(" ".join(
            ["Weight Goal:", self.goal_weight, self.units]))
        update_weight_goal_label = QPushButton("Update")
        update_weight_goal_label.clicked.connect(
            lambda: self.update_value("Weight Goal", self.goal_weight))
        weight_goal_layout.addWidget(self.weight_goal_label)
        weight_goal_layout.addWidget(update_weight_goal_label)

        loss_per_week_layout = QHBoxLayout()
        self.loss_per_week_label = QLabel(" ".join(
            ["Loss Per Week:",
             str(self.loss_per_week), self.units]))
        update_loss_per_week_label = QPushButton("Update")
        update_loss_per_week_label.clicked.connect(
            lambda: self.update_value("Loss Per Week", self.loss_per_week))
        loss_per_week_layout.addWidget(self.loss_per_week_label)
        loss_per_week_layout.addWidget(update_loss_per_week_label)

        calorie_intake_layout = QHBoxLayout()
        calorie_intake_label = QLabel(" ".join(
            ["Calorie Intake:",
             str(self.calorie_goal), "kcal"]))
        calorie_intake_layout.addWidget(calorie_intake_label)

        history_layout = QHBoxLayout()
        weight_loss_history_button = QPushButton("History")
        weight_loss_history_button.clicked.connect(
            lambda: self.show_weight_history())
        history_layout.addWidget(weight_loss_history_button)

        weight_loss.addWidget(main_label)
        weight_loss.addLayout(calorie_intake_layout)
        weight_loss.addLayout(current_weight_layout)
        weight_loss.addLayout(weight_goal_layout)
        weight_loss.addLayout(loss_per_week_layout)
        weight_loss.addLayout(history_layout)

        weight_loss.setSpacing(5)
        framed_layout = QFrame()
        framed_layout.setObjectName("graphObj")
        framed_layout.setFrameStyle(QFrame.Box)
        framed_layout.setLineWidth(3)
        framed_layout.setStyleSheet("""#graphObj {color: #322d2d;}""")

        framed_layout.setLayout(weight_loss)

        return framed_layout

    def create_cardio_notes(self):
        cardio_notes = QVBoxLayout()
        main_label = QLabel("Cardio Notes")
        main_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        preferred_activity_layout = QHBoxLayout()
        self.preferred_activity_label = QLabel(" ".join(
            ["Preferred Activity:", self.preferred_activity]))
        self.preferred_activity_dropdown = QComboBox()
        self.preferred_activity_dropdown.addItems(
            ["Running", "Walking", "Cycling", "Swimming"])
        self.preferred_activity_dropdown.setCurrentText(
            self.preferred_activity)
        self.preferred_activity_dropdown.currentTextChanged.connect(
            lambda activity: self.set_new_preferred_activity(activity))

        preferred_activity_layout.addWidget(self.preferred_activity_label)
        preferred_activity_layout.addWidget(self.preferred_activity_dropdown)

        time_spent_layout = QHBoxLayout()
        self.time_spent_label = QLabel(" ".join(
            ["Time Spent:", self.time_spent, "min"]))
        update_time_spent_label = QPushButton("Update")
        update_time_spent_label.clicked.connect(
            lambda: self.update_value("Time Spent", self.time_spent))
        time_spent_layout.addWidget(self.time_spent_label)
        time_spent_layout.addWidget(update_time_spent_label)

        calories_burnt_layout = QHBoxLayout()
        self.calories_burnt_label = QLabel(" ".join(
            ["Calories Burnt:", self.calories_burnt, "kcal"]))
        update_calories_burnt_label = QPushButton("Update")
        update_calories_burnt_label.clicked.connect(
            lambda: self.update_value("Calories Burnt", self.calories_burnt))
        calories_burnt_layout.addWidget(self.calories_burnt_label)
        calories_burnt_layout.addWidget(update_calories_burnt_label)

        distance_travelled_layout = QHBoxLayout()
        self.distance_travelled_label = QLabel(" ".join(
            ["Distance Travelled:", self.distance_travelled, "m"]))
        update_distance_travelled_label = QPushButton("Update")
        update_distance_travelled_label.clicked.connect(
            lambda: self.update_value("Distance Travelled", self.
                                      distance_travelled))
        distance_travelled_layout.addWidget(self.distance_travelled_label)
        distance_travelled_layout.addWidget(update_distance_travelled_label)

        history_layout = QHBoxLayout()
        cardio_history_button = QPushButton("History")
        cardio_history_button.clicked.connect(
            lambda: self.show_cardio_history())
        self.save_changes_cardio_button = QPushButton("Save Changes")
        self.save_changes_cardio_button.clicked.connect(
            lambda: self.add_cardio_entry_to_cardio_history())
        history_layout.addWidget(cardio_history_button)
        history_layout.addWidget(self.save_changes_cardio_button)

        cardio_notes.addWidget(main_label)
        cardio_notes.addLayout(preferred_activity_layout)
        cardio_notes.addLayout(time_spent_layout)
        cardio_notes.addLayout(distance_travelled_layout)
        cardio_notes.addLayout(calories_burnt_layout)
        cardio_notes.addLayout(history_layout)

        cardio_notes.setSpacing(5)
        framed_layout = QFrame()
        framed_layout.setObjectName("graphObj")
        framed_layout.setFrameStyle(QFrame.Box)
        framed_layout.setLineWidth(3)
        framed_layout.setStyleSheet("""#graphObj {color: #322d2d;}""")

        framed_layout.setLayout(cardio_notes)

        return framed_layout

    def update_value(self, to_edit, old_value):
        fitness_goal = None
        date = None
        if not to_edit == "Calories Burnt":
            if to_edit == "Loss Per Week":
                fitness_goal = self.user_data["Goal Params"][0]
            elif to_edit == "Current Weight":
                date = self.date
            self.dialog = WeightLossEditDialog(to_edit, old_value,
                                               fitness_goal, date)
            self.dialog.update_label_signal.connect(
                lambda label_to_update: self.update_weight_loss_label(
                    label_to_update))
            self.dialog.update_cardio_notes_signal.connect(
                lambda value_to_update: self.update_cardio_notes_label(
                    to_edit, value_to_update))
            self.dialog.update_graph_signal.connect(
                lambda signal: self.refresh_graph(signal))
        else:
            self.dialog = CaloriesBurntDialog(to_edit, old_value,
                                              self.time_spent,
                                              self.distance_travelled,
                                              self.preferred_activity,
                                              self.current_weight)
            self.dialog.update_calories_label_signal.connect(
                lambda value_to_update: self.update_cardio_notes_label(
                    to_edit, value_to_update))
        self.dialog.show()

    @pyqtSlot(bool)
    def update_weight_loss_label(self, signal):
        if signal:
            self.fetch_user_data()
            self.current_weight_label.setText(" ".join(
                ["Current Weight:",
                 str(self.current_weight), self.units]))
            self.weight_goal_label.setText(" ".join(
                ["Weight Goal:",
                 str(self.goal_weight), self.units]))
            self.loss_per_week_label.setText(" ".join(
                ["Loss Per Week:",
                 str(self.loss_per_week), self.units]))

    @pyqtSlot(str)
    def update_cardio_notes_label(self, to_edit, value_to_update):
        if to_edit == "Time Spent":
            self.time_spent = value_to_update
            self.time_spent_label.setText(" ".join(
                ["Time Spent:", str(value_to_update), "min"]))
        elif to_edit == "Distance Travelled":
            self.distance_travelled = value_to_update
            self.distance_travelled_label.setText(" ".join(
                ["Distance Travelled:",
                 str(value_to_update), "m"]))
        elif to_edit == "Calories Burnt":
            self.calories_burnt = value_to_update
            self.calories_burnt_label.setText(" ".join(
                ["Calories Burnt",
                 str(value_to_update), "kcal"]))

    def fetch_user_data(self):
        self.user_data = self.db_wrapper.fetch_local_user_info()
        self.current_weight = self.user_data["Weight"]
        self.goal_weight = self.user_data["Weight Goal"]
        self.loss_per_week = self.user_data["Goal Params"][1]

    def show_weight_history(self):
        self.history = WeightLossHistory()
        self.history.update_weight_loss_label_signal.connect(
            lambda signal: self.update_weight_loss_label(signal))
        self.history.setGeometry(100, 200, 300, 300)
        self.history.show()

    def show_cardio_history(self):
        self.cardio_history_dialog = CardioHistory()
        self.cardio_history_dialog.refresh_cardio_labels_signal.connect(
            lambda signal: self.refresh_cardio_notes(signal))
        self.cardio_history_dialog.setGeometry(100, 200, 300, 300)
        self.cardio_history_dialog.show()

    @pyqtSlot(bool)
    def refresh_cardio_notes(self, signal):
        if signal:
            self.cardio_history = json.loads(
                self.db_wrapper.fetch_local_column(self.table_name,
                                                   "cardio_history"))
            self.init_cardio_labels()
            self.time_spent_label.setText(" ".join(
                ["Time Spent:", self.time_spent, "min"]))
            self.distance_travelled_label.setText(" ".join(
                ["Distance Travelled:", self.distance_travelled, "m"]))
            self.calories_burnt_label.setText(" ".join(
                ["Calories Burnt:", self.calories_burnt, "kcal"]))

    def set_new_preferred_activity(self, activity):
        self.preferred_activity = activity
        self.preferred_activity_label.setText(" ".join(
            ["Preferred Activity:", activity]))
        self.preferred_activity_dropdown.setCurrentText(activity)
        self.db_wrapper.update_table_column(self.table_name,
                                            "preferred_activity",
                                            self.preferred_activity)
        self.init_cardio_labels()
        self.time_spent_label.setText(" ".join(
            ["Time Spent:", self.time_spent, "min"]))
        self.distance_travelled_label.setText(" ".join(
            ["Distance Travelled:", self.distance_travelled, "m"]))
        self.calories_burnt_label.setText(" ".join(
            ["Calories Burnt:", self.calories_burnt, "kcal"]))

    def init_cardio_labels(self):
        if len(self.cardio_history[self.date][self.preferred_activity]) > 0:
            self.today_exercise = self.cardio_history[self.date][
                self.preferred_activity][-1]
            self.time_spent = self.today_exercise["Time Spent"]
            self.distance_travelled = self.today_exercise["Distance Travelled"]
            self.calories_burnt = self.today_exercise["Calories Burnt"]
        else:
            self.time_spent = "0"
            self.distance_travelled = "0"
            self.calories_burnt = "0"

    def add_date_to_cardio_history(self):
        activities = ["Running", "Walking", "Cycling", "Swimming"]
        self.cardio_history[self.date] = {}
        for activity in activities:
            self.cardio_history[self.date][activity] = []

        cardio_history = json.dumps(self.cardio_history)
        self.db_wrapper.update_table_column(self.table_name, "cardio_history",
                                            cardio_history)

    def add_cardio_entry_to_cardio_history(self):
        date = datetime.today().strftime("%d/%m/%Y")
        new_entry = {
            "Time Spent": str(self.time_spent),
            "Distance Travelled": str(self.distance_travelled),
            "Calories Burnt": str(self.calories_burnt)
        }
        self.cardio_history[date][self.preferred_activity].append(new_entry)
        current_cardio_history = json.dumps(self.cardio_history)
        self.db_wrapper.update_table_column(self.table_name, "cardio_history",
                                            current_cardio_history)

    def add_date_to_weight_history(self):
        try:
            last_entry = list(self.weight_history.values())[-1]
            self.weight_history[self.date] = last_entry
            self.db_wrapper.update_table_column(
                self.table_name, "weight_history",
                json.dumps(self.weight_history))
        except IndexError:  # no records
            pass

    @pyqtSlot(bool)
    def refresh_graph(self, signal):
        if signal:
            self.weight_history = self.db_wrapper.fetch_local_column(
                self.table_name, "weight_history")
            self.replace_graph(str(self.months_combobox.currentText()))

    def replace_graph(self, month):
        new_graph = WeightLossGraphCanvas(month, self.current_year, self)
        new_toolbar = NavigationToolbar(new_graph, self)

        old_toolbar_reference = self.graph_layout.itemAt(0).widget()
        old_graph_reference = self.graph_layout.itemAt(1).widget()

        self.graph_layout.replaceWidget(old_toolbar_reference, new_toolbar)
        self.graph_layout.replaceWidget(old_graph_reference, new_graph)

    def change_year_graph(self, year):
        self.current_year = year
        self.replace_graph(str(self.months_combobox.currentText()))

    def change_month_graph(self, month):
        self.replace_graph(str(month))
class WorkoutPlanner(QWidget):
    def __init__(self):
        super().__init__()
        self.setStyleSheet("""
    QWidget{
      color:#c7c7c7;
      font-weight: bold;
    }
    QPushButton{
      background-color: rgba(0, 0, 0, 0);
      border: 1px solid;
      font-size: 18px;
      font-weight: bold;
      border-color: #808080;
      min-height: 28px;
      white-space:nowrap;
      text-align: left;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
      border-color: #6C6C6C;
    }""")

        self.db_wrapper = DatabaseWrapper()
        self.table_name = "Workouts"
        self.db_wrapper.create_local_table(self.table_name)
        if self.db_wrapper.local_table_is_empty(self.table_name):
            self.db_wrapper.insert_default_values(self.table_name)
        self.fetched_workouts = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name, "workouts"))
        self.current_date = datetime.today().strftime("%d/%m/%Y")
        if not self.current_date in self.fetched_workouts:
            self.fetched_workouts[self.current_date] = {
                "Personal Notes": "",
                "Workout Name": "None"
            }
            self.db_wrapper.update_table_column(
                self.table_name, "workouts", json.dumps(self.fetched_workouts))
        self.create_panel()

    def create_panel(self):
        self.grid = QGridLayout()
        self.grid.addWidget(self.create_calendar(), 0, 0, 2, 1)
        self.grid.addWidget(self.create_stats(), 0, 1, 2, 1)
        self.grid.addWidget(self.create_left_details(), 2, 0, 2, 1)
        self.grid.addWidget(self.create_right_details(), 2, 1, 2, 1)
        self.setLayout(self.grid)

    def create_calendar(self):
        frame = QFrame()
        frame.setFrameStyle(QFrame.StyledPanel)

        layout = QHBoxLayout()

        self.calendar = QCalendarWidget(self)
        self.calendar.setLocale(QLocale(QLocale.English))
        self.calendar.setFirstDayOfWeek(Qt.DayOfWeek.Monday)
        self.calendar.clicked.connect(lambda: self.show_date())
        layout.addWidget(self.calendar)

        frame.setLayout(layout)

        return frame

    def create_stats(self):
        frame = QFrame()
        frame.setFrameStyle(QFrame.StyledPanel)

        stats_layout = QVBoxLayout()
        stats_label = QLabel("Stats")
        stats_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        number_of_workouts = QLabel(" ".join([
            "Total Number Of Workouts Done:",
            str(len(self.fetched_workouts))
        ]))

        counter_this_month = 0
        for date in self.fetched_workouts:
            if date.split("/")[1] == self.current_date.split("/")[1]:
                counter_this_month += 1

        workouts_done_this_month = QLabel(" ".join(
            ["Workouts Done This Month:",
             str(counter_this_month)]))

        last_workout = list(self.fetched_workouts.keys())[-1]
        for date, workout in reversed(list(self.fetched_workouts.items())):
            if len(workout) > 1:  # found workout that is not todays default
                last_workout = date
                break
        last_workout = QLabel(" ".join(["Last Workout:", last_workout]))

        stats_layout.addWidget(stats_label)
        stats_layout.addWidget(number_of_workouts)
        stats_layout.addWidget(workouts_done_this_month)
        stats_layout.addWidget(last_workout)

        frame.setLayout(stats_layout)

        return frame

    def create_left_details(self):
        frame = QFrame()
        frame.setFrameStyle(QFrame.StyledPanel)

        layout = QVBoxLayout()

        self.day_label = QLabel(self.current_date)
        self.day_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        workout_done_layout = QHBoxLayout()
        self.workout_done_label = QLabel(" ".join([
            "Workout Done:",
            self.fetched_workouts[self.current_date]["Workout Name"]
        ]))
        workout_done_button = QPushButton("Change")
        workout_done_button.clicked.connect(lambda: self.change_workout_done())
        workout_done_layout.addWidget(self.workout_done_label)
        workout_done_layout.addWidget(workout_done_button)

        specific_workout_layout = QHBoxLayout()
        specific_workout_label = QLabel(
            "Create a workout specific for one day: ")
        specific_workout_button = QPushButton("1 Time Workout")
        specific_workout_button.clicked.connect(
            lambda: self.show_1_time_window())
        specific_workout_layout.addWidget(specific_workout_label)
        specific_workout_layout.addWidget(specific_workout_button)

        personal_notes_layout = QVBoxLayout()
        personal_notes_label = QLabel("Personal Notes:")
        self.text_edit = QTextEdit()
        self.text_edit.setStyleSheet("color: black;")
        self.text_edit.setText(
            self.fetched_workouts[self.current_date]["Personal Notes"])
        self.personal_notes_save_button = QPushButton("Save Changes")
        self.personal_notes_save_button.clicked.connect(
            lambda: self.update_personal_notes())
        personal_notes_layout.addWidget(personal_notes_label)
        personal_notes_layout.addWidget(self.text_edit)
        personal_notes_layout.addWidget(self.personal_notes_save_button)

        layout.addWidget(self.day_label)
        layout.addLayout(workout_done_layout)
        layout.addLayout(specific_workout_layout)
        layout.addLayout(personal_notes_layout)
        frame.setLayout(layout)

        return frame

    def create_right_details(self):
        frame = QFrame()
        frame.setFrameStyle(QFrame.StyledPanel)

        layout = QVBoxLayout()
        layout.setAlignment(Qt.AlignTop)

        details_label = QLabel("Workout Details")
        details_label.setFont(QFont("Ariel", 18, weight=QFont.Bold))

        self.grid_layout = QGridLayout()
        name_label = QLabel("Exercise Name")
        sets_label = QLabel("Sets")
        reps_label = QLabel("Reps")
        rest_label = QLabel("Rest")

        layout.addWidget(details_label)
        self.grid_layout.addWidget(name_label, 0, 0)
        self.grid_layout.addWidget(sets_label, 0, 1)
        self.grid_layout.addWidget(reps_label, 0, 2)
        self.grid_layout.addWidget(rest_label, 0, 3)

        if "Exercises" in self.fetched_workouts[self.current_date]:
            exercises_count = len(
                self.fetched_workouts[self.current_date]["Exercises"])

            self.number_of_exercises_label = QLabel(" ".join(
                ["Number of Exercises:",
                 str(exercises_count)]))

            set_count = 0

            for exercise in self.fetched_workouts[
                    self.current_date]["Exercises"]:
                set_count += int(self.fetched_workouts[self.current_date]
                                 ["Exercises"][exercise]["Sets"])

            self.total_set_count_label = QLabel(" ".join(
                ["Total Set Count:", str(set_count)]))

            layout.addWidget(self.number_of_exercises_label)
            layout.addWidget(self.total_set_count_label)

            names_labels = [None] * len(
                self.fetched_workouts[self.current_date]["Exercises"].keys())
            sets_labels = [None] * len(
                self.fetched_workouts[self.current_date]["Exercises"].keys())
            reps_labels = [None] * len(
                self.fetched_workouts[self.current_date]["Exercises"].keys())
            rest_labels = [None] * len(
                self.fetched_workouts[self.current_date]["Exercises"].keys())

            j = 1
            for i, exercise in enumerate(self.fetched_workouts[
                    self.current_date]["Exercises"].keys()):
                names_labels[i] = QLabel(exercise)
                sets_labels[i] = QLabel(
                    str(self.fetched_workouts[self.current_date]["Exercises"]
                        [exercise]["Sets"]))
                reps_labels[i] = QLabel(
                    str(self.fetched_workouts[self.current_date]["Exercises"]
                        [exercise]["Reps"]))
                rest_labels[i] = QLabel(
                    str(self.fetched_workouts[self.current_date]["Exercises"]
                        [exercise]["Rest"]))

                self.grid_layout.addWidget(names_labels[i], j, 0)
                self.grid_layout.addWidget(sets_labels[i], j, 1)
                self.grid_layout.addWidget(reps_labels[i], j, 2)
                self.grid_layout.addWidget(rest_labels[i], j, 3)
                j += 1

        layout.addWidget(QLabel(""))
        layout.addLayout(self.grid_layout)
        frame.setLayout(layout)

        return frame

    def show_date(self):
        self.current_date = self.get_calendar_date()
        if not self.current_date in self.fetched_workouts:
            self.fetched_workouts[self.current_date] = {
                "Personal Notes": "",
                "Workout Name": "None"
            }
        self.day_label.setText(self.current_date)
        self.refresh_workout_done(True, True)
        self.text_edit.setText(
            self.fetched_workouts[self.current_date]["Personal Notes"])

    def get_calendar_date(self):
        date = self.calendar.selectedDate()
        day = str(date.day()) if date.day() > 9 else "0" + str(date.day())
        month = str(
            date.month()) if date.month() > 9 else "0" + str(date.month())
        parsed_date = "/".join([day, month, str(date.year())])
        return parsed_date

    def show_1_time_window(self):
        self.create_workout_window = CreateWorkoutWindow(
            one_time=True, date=self.get_calendar_date())
        if self.db_wrapper.connection_exists:
            self.create_workout_window.refresh_after_creating_signal.connect(
                lambda signal: self.refresh_workout_done(signal))
        self.create_workout_window.setGeometry(100, 200, 300, 300)
        self.create_workout_window.show()

    def update_personal_notes(self):
        self.fetched_workouts[self.current_date][
            "Personal Notes"] = self.text_edit.toPlainText()
        self.db_wrapper.update_table_column(self.table_name, "workouts",
                                            json.dumps(self.fetched_workouts))

    def change_workout_done(self):
        self.select_workout_window = SelectWorkout(self.get_calendar_date())
        self.select_workout_window.refresh_workout_done_signal.connect(
            lambda signal: self.refresh_workout_done(signal))
        self.select_workout_window.setGeometry(100, 200, 300, 300)
        self.select_workout_window.show()

    @pyqtSlot(bool)
    def refresh_workout_done(self, signal, date_change=False):
        if signal:
            if not date_change:
                self.fetched_workouts = json.loads(
                    self.db_wrapper.fetch_local_column(self.table_name,
                                                       "workouts"))
            self.workout_done_label.setText(" ".join([
                "Workout Done:",
                self.fetched_workouts[self.current_date]["Workout Name"]
            ]))
            old_right_details_reference = self.grid.itemAt(3).widget()
            new_right_details = self.create_right_details()
            self.grid.replaceWidget(old_right_details_reference,
                                    new_right_details)
            old_right_details_reference.setParent(None)