def __init__(self, email, password):
     super().__init__()
     self.setStyleSheet("""
 QWidget{
   background-position: center;
   color: #D9D9D9;
   font-family: Montserrat;
   font-size: 14px;
 }
 QPushButton{
   border-radius: 1px;
   background-color: #440D0F;
 }
 QPushButton:hover:!pressed{
   background-color: #5D1A1D
 }
 QPushButton:pressed{
   background-color: #551812
 }    
 QLineEdit{
   padding: 6px;
   background-color: rgb(33,33,33);
   border-radius: 2px;
 }
 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 = DatabaseWrapper()
     self.email = email
     self.password = password
     self.create_panel()
Example #2
0
    def __init__(self, table_name, db_path="test.db"):
        self.test_user = {
            "email":
            "*****@*****.**",
            "password":
            hashlib.sha256("testpassword123".encode('UTF-8')).hexdigest(),
            "name":
            "Test",
            "age":
            "18",
            "gender":
            "male",
            "units":
            "metric",
            "weight":
            "100",
            "height":
            "190",
            "goal":
            "Weight gain",
            "goalparams":
            json.dumps(["Moderately active", 0.25]),
            "goalweight":
            "120"
        }

        self.test_password = "******"
        self.db_path = db_path
        self.table_name = table_name

        self.db_wrapper = DatabaseWrapper(self.db_path)
        self.sqlite_connection = self.db_wrapper.sqlite_connection
        self.sqlite_cursor = self.sqlite_connection.cursor()
        self.pg_connection = self.db_wrapper.pg_connection
        self.pg_cursor = self.pg_connection.cursor()
Example #3
0
 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()
Example #4
0
 def __init__(self):
   super().__init__()
   self.db_wrapper = DatabaseWrapper()
   self.setStyleSheet("""
   QWidget{
     background-position: center;
     font-family: Montserrat;
     color: #D9D9D9;
     font-size: 14px;
   }
   QPushButton{
     border-radius: 1px;
     background-color: #440D0F;
   }
   QPushButton:hover:!pressed{
     background-color: #5D1A1D
   }
   QPushButton:pressed{
     background-color: #551812
   }    
   QLineEdit{
     padding: 6px;
     background-color: rgb(33,33,33);
     border-radius: 2px;
   }
   """)
   self.create_panel()
Example #5
0
 def __init__(self, parent):
     super().__init__(parent)
     self.db_wrapper = DatabaseWrapper()
     self.create_panel()
     self.setMaximumWidth(201)
     self.setStyleSheet("""
                    QPushButton{
                      text-align: center;
                      background-color: #440D0F;
                      border-radius: 3px;
                      min-height: 23px;
                      min-width: 180px;
                      color: #c7c7c7;
                      font: 15px;
                      font-weight:500;
                      font-family:Montserrat;
                      padding-bottom: 3px;
                      }
                    QPushButton:hover:!pressed{
                      background-color: #5D1A1D
                    }
                    QPushButton:pressed{
                      background-color: #551812
                    }
                    """)
Example #6
0
 def setUp(self):
   self.test_class = TestClass("big_lifts", "test.db")
   self.db_wrapper = DatabaseWrapper("test.db")
   
   self.table_name = "Compound Exercises"
   self.test_class.create_test_user()
   self.db_wrapper.create_local_table("Compound Exercises")
   self.db_wrapper.insert_default_values("Compound Exercises")
Example #7
0
    def __init__(self, to_edit, old_value, fitness_goal=None, date=None):
        super().__init__()
        assert to_edit in ("Current Weight", "Weight Goal", "Loss Per Week",
                           "Time Spent", "Distance Travelled")
        if to_edit == "Loss Per Week":
            assert fitness_goal != None
            self.fitness_goal = fitness_goal
        elif to_edit == "Current Weight":
            assert date != None
            self.date = date

        self.db_wrapper = DatabaseWrapper()
        self.table_name = "Weight Loss"
        self.to_edit = to_edit
        self.old_value = old_value
        self.current_date = datetime.today().strftime("%d/%m/%Y")
        self.setStyleSheet("""QWidget{
      background-color: #232120;
      color:#c7c7c7;
      font-weight: bold;
      font-family: Montserrat;
      font-size: 16px;
      }
    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;
    }
    QLineEdit{
      padding: 6px;
      background-color: rgb(33,33,33);
      border: 1px solid;
      border-color: #cdcdcd;
    }""")
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowTitle("".join(["Edit ", self.to_edit]))
        self.layout = QVBoxLayout()
        self.layout.addLayout(self.create_layout())
        self.setLayout(self.layout)
Example #8
0
  def __init__(self, month, year, parent=None, width=5, height=4, dpi=100):
    figure = Figure(figsize=(width, height), dpi=dpi, tight_layout=True)
    FigureCanvas.__init__(self, figure)
    self.current_month = month
    self.current_year = year
    self.set_parent = parent
    self.db_wrapper = DatabaseWrapper()
    self.weight_history = json.loads(self.db_wrapper.fetch_local_column("Weight Loss", "weight_history"))

    self.axes = figure.subplots(nrows=1, ncols=1)
    self.create_figure()
    FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
    FigureCanvas.updateGeometry(self)
Example #9
0
    def __init__(self):
        super().__init__()
        self.setWindowIcon(QIcon(icon_path))
        QFontDatabase.addApplicationFont(
            os.path.join(os.path.dirname(__file__), "font",
                         "Montserrat-Regular.ttf"))
        QFontDatabase.addApplicationFont(
            os.path.join(os.path.dirname(__file__), "font",
                         "Ubuntu-Regular.ttf"))
        if getattr(sys, 'frozen', False):
            QFontDatabase.addApplicationFont(
                os.path.join(os.path.dirname(sys.executable), "font",
                             "Montserrat-Regular.ttf"))
            QFontDatabase.addApplicationFont(
                os.path.join(os.path.dirname(sys.executable), "font",
                             "Ubuntu-Regular.ttf"))

        self.db_wrapper = DatabaseWrapper()

        self.create_window()
        if self.db_wrapper.local_table_exists("Users"):
            if not self.db_wrapper.one_logged_in_user(): self.cw = Login()
            else: self.cw = BigLiftsNotes()
        else:
            self.cw = Login()
        self.cw.display_layout_signal.connect(
            lambda layout: self.display_layout(layout))
        self.layouts = {
            "Login": Login,
            "Signup": Signup,
            "Continue": SignupQuestions,
            "Profile": Profile,
            "Logout": Login,
            "Compound Exercises": BigLiftsNotes,
            "Workout Planner": WorkoutsNotes,
            "Exercises and Workouts": WorkoutsNotes,
            "Nutrition": NutritionNotes,
            "Weight Loss": WeightLossNotes,
            "1 Rep Max Calculator": OneRepMaxCalculator,
            "Body Fat Calculator": BodyFatCalculator,
            "Strength Estimator": StrengthEstimator,
            "Food Database": FoodDB
        }
        self.colorize_background()
        self.colorize_foreground()
        self.setup_borders()
        self.title_bar = TitleBar(self)
        self.setMouseTracking(True)
        #add funct that generates default config file if 'settings.ini' isn't found
        main_widget = self.setup_main_layout()
        self.setCentralWidget(main_widget)
    def __init__(self):
        super().__init__()
        self.db_wrapper = DatabaseWrapper()
        self.table_name = "Weight Loss"
        self.setStyleSheet("""
    QWidget{
      background-color: #232120;
      font-weight: bold;
      color:#c7c7c7;
    }
    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: center;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
    }
    """)
        self.units = "kg" if self.db_wrapper.fetch_local_column(
            "Users", "units") == "metric" else "lb"
        self.cardio_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "cardio_history"))
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowTitle("Cardio History")

        widget = QWidget()
        self.layout = QGridLayout(widget)
        self.setWidget(widget)
        self.setWidgetResizable(True)

        self.entry_count = 0
        for date in self.cardio_history:
            for activity in self.cardio_history[date]:
                self.entry_count += len(self.cardio_history[date][activity])
        self.create_history(True, True)
Example #11
0
 def __init__(self, parent):
     super().__init__()
     self.db_wrapper = DatabaseWrapper()
     self.setStyleSheet("""
 QWidget{
   font-family: Montserrat;
   color:#c7c7c7;
   font-weight: bold;      
   font-size:12px;
 }
 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;
 }
 QLineEdit{
   padding: 6px;
   background-color: rgb(33,33,33);
   border-radius: 2px;
 }
 QTableWidget{
   background-color: rgb(33,33,33);  
   border: 1px solid;
   border-color: rgb(88, 88, 88);
   font-size: 14px;
 }
 QHeaderView:section{
   background-color: rgb(54,54,54);  
   border: 1px solid;
   border-color: rgb(88, 88, 88)
 }
 """)
     self.create_panel()
Example #12
0
 def __init__(self, lift_type, rm_history, year, parent=None, width=5, height=4, dpi=100):
   assert lift_type in ["Horizontal Press", "Floor Pull", "Squat", "Vertical Press"], "Invalid lift type: '%s'" % lift_type
   self.db_wrapper = DatabaseWrapper()
   self.lift_type = lift_type
   self.rm_history = rm_history
   self.year = year
   
   fig = Figure(figsize=(width, height), dpi=dpi, tight_layout=True)
   FigureCanvas.__init__(self, fig)
   
   self.axes = fig.subplots(nrows=1, ncols=1)
   self.create_figure()
   self.set_parent = parent
   FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
   FigureCanvas.updateGeometry(self)
Example #13
0
class WeightLossGraphCanvas(FigureCanvas):
  def __init__(self, month, year, parent=None, width=5, height=4, dpi=100):
    figure = Figure(figsize=(width, height), dpi=dpi, tight_layout=True)
    FigureCanvas.__init__(self, figure)
    self.current_month = month
    self.current_year = year
    self.set_parent = parent
    self.db_wrapper = DatabaseWrapper()
    self.weight_history = json.loads(self.db_wrapper.fetch_local_column("Weight Loss", "weight_history"))

    self.axes = figure.subplots(nrows=1, ncols=1)
    self.create_figure()
    FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
    FigureCanvas.updateGeometry(self)
  
  def create_figure(self):
    self.parsed_weight_entries = self.parse_weight_history()
    days_in_a_month = [monthrange(int(self.current_year), month)[1] for month in range(1, 13)]
    self.axes.plot(self.parsed_weight_entries, marker='o')
    days = list(range(1, days_in_a_month[list(self.db_wrapper.months_mappings.keys()).index(self.current_month)]))
    self.axes.set_xticks(days)
    self.axes.set_yticks(self.parsed_weight_entries)
    self.axes.grid(self.current_month)
    self.axes.set_title(self.current_month)

  def parse_weight_history(self):
    weights = []
    for entry in self.weight_history:
      entry = entry.split("/")
      if entry[1] == self.db_wrapper.months_mappings[self.current_month] and entry[2] == str(self.current_year):
        weights.append(float(self.weight_history["/".join(entry)])) 
    return weights
Example #14
0
 def __init__(self):
     super().__init__()
     self.db_wrapper = DatabaseWrapper()
     self.table_name = "Nutrition"
     self.user_data = self.db_wrapper.fetch_local_user_info()
     self.user_weight = self.user_data["Weight"]
     self.goal_weight = self.user_data["Weight Goal"]
     goal_parameters = self.user_data["Goal Params"]
     self.goal = self.user_data["Goal"]
     self.activity_level = goal_parameters[0]
     self.weight_per_week = goal_parameters[1]
     self.age = self.user_data["Age"]
     self.gender = self.user_data["Gender"]
     self.height = self.user_data["Height"]
     self.setWindowTitle("Edit weight")
     self.create_layout()
 def __init__(self, cardio_history, date, activity, index):
     super().__init__()
     self.db_wrapper = DatabaseWrapper()
     self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
     self.setWindowModality(Qt.ApplicationModal)
     self.table_name = "Weight Loss"
     self.cardio_history = cardio_history
     self.date = date
     self.activity = activity
     self.index = index
     self.entry = self.cardio_history[self.date][self.activity][self.index]
     self.setStyleSheet("""
 QWidget{
   background-color: #322d2d;
   font-weight: bold;
   color:#c7c7c7;
 }
 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: center;
   padding-left: 5%;
   font-family: Montserrat;
 }
 QPushButton:hover:!pressed{
   border: 2px solid;
   border-color: #747474;
 }
 QPushButton:pressed{
   border: 2px solid;
   background-color: #323232;
 }
 """)
     self.units = "kg" if self.db_wrapper.fetch_local_column(
         "Users", "units") == "metric" else "lb"
     self.cardio_history = json.loads(
         self.db_wrapper.fetch_local_column(self.table_name,
                                            "cardio_history"))
     self.setWindowModality(Qt.ApplicationModal)
     self.setWindowFlags(Qt.Tool)
     self.setWindowTitle("Edit Cardio History Entry")
     self.create_layout()
Example #16
0
 def __init__(self, parent, search_results):
     super().__init__(parent)
     self.query_number = 6
     self.search = search_results[1]
     self.search_results = search_results[0]
     self.create_panel()
     self.setStyleSheet("QLabel{color:white;}")
     self.db_wrapper = DatabaseWrapper()
Example #17
0
 def __init__(self, age, gender, height, weight, activity_level, goal, weight_per_week):
   self.db_wrapper = DatabaseWrapper()
   self.units = self.db_wrapper.fetch_local_column("Users", "units")
   self.age = age
   self.gender = gender
   activity_factors = {"Maintain": 1, "Sedentary": 1.2, "Lightly active": 1.375,
                       "Moderately active": 1.550, "Very active": 1.725,
                       "Extra active": 1.9}
   self.activity_level = activity_factors[activity_level]
   if self.units == "imperial":
     self.height = imperial_to_metric_height(height["feet"], height["inches"])
     self.weight = pounds_to_kg(weight)
   else:
     self.height = height
     self.weight = weight
   self.goal = goal
   self.weight_per_week = weight_per_week
    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()
Example #19
0
class OneRMGraphCanvas(FigureCanvas):
  def __init__(self, lift_type, rm_history, year, parent=None, width=5, height=4, dpi=100):
    assert lift_type in ["Horizontal Press", "Floor Pull", "Squat", "Vertical Press"], "Invalid lift type: '%s'" % lift_type
    self.db_wrapper = DatabaseWrapper()
    self.lift_type = lift_type
    self.rm_history = rm_history
    self.year = year
    
    fig = Figure(figsize=(width, height), dpi=dpi, tight_layout=True)
    FigureCanvas.__init__(self, fig)
    
    self.axes = fig.subplots(nrows=1, ncols=1)
    self.create_figure()
    self.set_parent = parent
    FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
    FigureCanvas.updateGeometry(self)
  
  def create_figure(self):
    self.parsed_exercises = self.parse_data()
    months = ["January", "February", "March", "April", "May", "June", "July",
              "August", "September", "October", "November", "December"]
    self.axes.plot(months, self.parsed_exercises[self.preferred_lifts[self.lift_type]], marker='o')
    self.axes.set_yticks(self.parsed_exercises[self.preferred_lifts[self.lift_type]])
    for label in self.axes.get_xticklabels():
      label.set_rotation(45)
    self.axes.grid()
    self.axes.set_title(self.preferred_lifts[self.lift_type])
     
  def parse_data(self):
    self.preferred_lifts = json.loads(self.db_wrapper.fetch_local_column("Compound Exercises", "preferred_lifts"))
    parsed_exercises = {self.preferred_lifts["Horizontal Press"]: [], self.preferred_lifts["Floor Pull"]: [],
                        self.preferred_lifts["Squat"]: [], self.preferred_lifts["Vertical Press"]: []}

    horizontal_press = self.preferred_lifts["Horizontal Press"]
    floor_pull = self.preferred_lifts["Floor Pull"]
    squat = self.preferred_lifts["Squat"]
    vertical_press = self.preferred_lifts["Vertical Press"]

    for month in self.rm_history[self.year]:
      current_month = self.rm_history[self.year][month]
      
      horizontal_press_values = list(map(float, current_month["Horizontal Press"][horizontal_press]))
      floor_pull_values = list(map(float, current_month["Floor Pull"][floor_pull]))
      squat_values = list(map(float, current_month["Squat"][squat]))
      vertical_press_values = list(map(float, current_month["Vertical Press"][vertical_press]))

      max_horizontal_press = max(horizontal_press_values) if len(horizontal_press_values) >= 1 else 0
      max_floor_pull = max(floor_pull_values) if len(floor_pull_values) >= 1 else 0
      max_squat = max(squat_values) if len(squat_values) >= 1 else 0
      max_vertical_press = max(vertical_press_values) if len(vertical_press_values) >= 1 else 0

      parsed_exercises[horizontal_press].append(max_horizontal_press)
      parsed_exercises[floor_pull].append(max_floor_pull)
      parsed_exercises[squat].append(max_squat)
      parsed_exercises[vertical_press].append(max_vertical_press)
  
    return parsed_exercises
Example #20
0
 def __init__(self, parent, edit_func):
     super().__init__()
     self.edit_func = edit_func
     self.this_parent = parent
     self.db_wrapper = DatabaseWrapper()
     self.setStyleSheet("""QWidget{
   background-color: #232120;
   color:#c7c7c7;
   font-weight: bold;
   font-family: Montserrat;
   font-size: 16px;
   }
 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;
 }
 QLineEdit{
   padding: 6px;
   background-color: rgb(33,33,33);
   border: 1px solid;
   border-color: #cdcdcd;
 }""")
     dialog_layout = QVBoxLayout()
     self.setWindowFlags(Qt.FramelessWindowHint)
     dialog_layout.addLayout(self.create_input_window())
     self.setLayout(dialog_layout)
 def __init__(self, workout_name=None, one_time=False, date=None):
   super().__init__()
   self.setStyleSheet("""
   QWidget{
     background-color: #232120;
     font-weight: bold;
     color:#c7c7c7;
   }
   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: center;
     padding-left: 5%;
     font-family: Montserrat;
   }
   QPushButton:hover:!pressed{
     border: 2px solid;
     border-color: #747474;
   }
   QPushButton:pressed{
     border: 2px solid;
     background-color: #323232;
   }
   """)
   self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
   self.setWindowModality(Qt.ApplicationModal)
   if workout_name != None:
     self.setWindowTitle("Edit Workout")
   else:
     self.setWindowTitle("Create a New Workout")
   self.db_wrapper = DatabaseWrapper()
   self.table_name = "Workouts"
   self.workout_name = workout_name
   self.one_time = one_time
   self.current_date = date
   self.fetched_my_workouts = json.loads(self.db_wrapper.fetch_local_column(self.table_name, "my_workouts"))
   self.create_panel()
Example #22
0
 def __init__(self, parent, edit_func, parameter):
     super().__init__()
     self.edit_func = edit_func
     self.this_parent = parent
     self.parameter = parameter  # goal or gender
     self.db_wrapper = DatabaseWrapper()
     self.setStyleSheet("""QWidget{
   background-color: #232120;
   color:#c7c7c7;
   font-weight: bold;
   font-family: Montserrat;
   font-size: 16px;
   }
 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;
 }""")
     dialog_layout = QVBoxLayout()
     self.setWindowFlags(Qt.FramelessWindowHint)
     self.setLayout(dialog_layout)
     if self.edit_func == "gender":
         layout = self.create_radio_button_gender()
     elif self.edit_func == "goal":
         layout = self.create_radio_button_goal()
     dialog_layout.addLayout(layout)
 def __init__(self):
     super().__init__()
     self.db_wrapper = DatabaseWrapper()
     self.table_name = "Compound Exercises"
     self.setStyleSheet("""
 QWidget{
   background-color: #232120;
   font-weight: bold;
   color:#c7c7c7;
 }
 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: center;
   padding-left: 5%;
   font-family: Montserrat;
 }
 QPushButton:hover:!pressed{
   border: 2px solid;
   border-color: #747474;
 }
 QPushButton:pressed{
   border: 2px solid;
   background-color: #323232;
 }
 """)
     self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
     self.setWindowModality(Qt.ApplicationModal)
     self.units = "kg" if self.db_wrapper.fetch_local_column(
         "Users", "units") == "metric" else "lb"
     self.preferred_lifts = json.loads(
         self.db_wrapper.fetch_local_column(self.table_name,
                                            "preferred_lifts"))
     self.setWindowTitle("Update Lifts For Reps")
     self.setLayout(self.create_panel())
     self.set_line_edit_values()
Example #24
0
class CalorieGoalCalculator:
  def __init__(self, age, gender, height, weight, activity_level, goal, weight_per_week):
    self.db_wrapper = DatabaseWrapper()
    self.units = self.db_wrapper.fetch_local_column("Users", "units")
    self.age = age
    self.gender = gender
    activity_factors = {"Maintain": 1, "Sedentary": 1.2, "Lightly active": 1.375,
                        "Moderately active": 1.550, "Very active": 1.725,
                        "Extra active": 1.9}
    self.activity_level = activity_factors[activity_level]
    if self.units == "imperial":
      self.height = imperial_to_metric_height(height["feet"], height["inches"])
      self.weight = pounds_to_kg(weight)
    else:
      self.height = height
      self.weight = weight
    self.goal = goal
    self.weight_per_week = weight_per_week
  
  def calculate_calorie_goal(self):
    if self.goal == "Maintain weight": return self.calculate_BMR()
    elif self.goal == "Weight loss": return self.calculate_weight_loss_goal(self.weight_per_week)
    elif self.goal == "Weight gain": return self.calculate_weight_gain_goal(self.weight_per_week)

  def calculate_BMR(self):
    """
    The Basal Metabolic Rate - amount of energy expended while at rest in a neutrally temperate environment, 
    and in a post-absorptive state (meaning that the digestive system is inactive, which requires about 12 hours of fasting).
    """
    equ = 10*self.weight+6.25*self.height-5*self.age # Mifflin-St Jeor Equation
    if self.gender == "male": equ += 5
    elif self.gender == "female": equ -= 161
    return round(equ*self.activity_level)

  def calculate_weight_loss_goal(self, weight_per_week):
    assert weight_per_week == 0.25 or weight_per_week == 0.5 or weight_per_week == 1 # kg
    calories_per_day = self.calculate_BMR()
    if weight_per_week == 0.25:
      return round(calories_per_day*0.89)
    elif weight_per_week == 0.5:
      return round(calories_per_day*0.78)
    elif weight_per_week == 1:
      return round(calories_per_day*0.56)
  
  def calculate_weight_gain_goal(self, weight_per_week):
    assert weight_per_week == 0.25 or weight_per_week == 0.5 or weight_per_week == 1 # kg
    calories_per_day = self.calculate_BMR()
    if weight_per_week == 0.25:
      return round(calories_per_day*1.11)
    elif weight_per_week == 0.5:
      return round(calories_per_day*1.22)
    elif weight_per_week == 1:
      return round(calories_per_day*1.44)
Example #25
0
 def __init__(self, layout_name):
     super().__init__()
     self.main_panel = ExercisesAndWorkouts(
     ) if layout_name == "Exercises and Workouts" else WorkoutPlanner()
     if layout_name == "Exercises and Workouts" and DatabaseWrapper(
     ).connection_exists:
         self.main_panel.show_muscle_group_signal.connect(
             lambda muscle_group: self.show_muscle_group_layout(muscle_group
                                                                ))
     self.side_panel = SidePanel(self)
     self.side_panel.emit_layout_name.connect(
         lambda layout_name: self.emit_display_layout_signal(layout_name))
     self.create_grid()
Example #26
0
class TestSignup(unittest.TestCase):
    def setUp(self):
        self.test_class = TestClass("users", "test.db")
        self.db_wrapper = DatabaseWrapper("test.db")
        self.test_class.create_test_user()

    def tearDown(self):
        self.test_class.delete_test_user()

    def test_create_user(self):
        name_and_password = self.test_class.fetch_remote_name_and_password()
        self.assertEqual(
            tuple([
                self.test_class.test_user["email"],
                self.test_class.test_user["password"]
            ]), name_and_password)

    def test_create_user_table(self):
        self.db_wrapper.create_user_table(
            self.test_class.test_user["email"],
            self.test_class.test_user["password"])
        columns = ('email', 'password', 'name', 'age', 'gender', 'units',
                   'weight', 'height', 'goal', 'goalparams', 'goalweight',
                   'logged_in')
        table_columns = self.test_class.fetch_column_names()
        table_data = self.test_class.fetch_all_local_columns()[0][:-1][0:2]

        self.assertEqual(table_columns, columns)
        self.assertEqual(
            table_data,
            tuple([
                self.test_class.test_user["email"],
                self.test_class.test_user["password"]
            ]))

    def test_create_user_info_after_signup(self):
        self.db_wrapper.create_user_table(
            self.test_class.test_user["email"],
            self.test_class.test_user["password"])
        user_info = {
            key: value
            for key, value in self.test_class.test_user.items()
            if not key == "email" and not key == "password"
        }
        info = copy.deepcopy(self.test_class.test_user)
        del info["email"]
        del info["password"]
        self.db_wrapper.create_user_info_after_signup(info)
        fetch_info = self.test_class.fetch_all_remote_columns()[0][:-1]
        self.assertEqual(fetch_info, tuple(self.test_class.test_user.values()))
Example #27
0
class LiftHistory(QScrollArea):
  def __init__(self):
    super().__init__()
    self.db_wrapper = DatabaseWrapper()
    self.table_name = "Compound Exercises"
    self.setStyleSheet("""
    QWidget{
      background-color: #232120;
      font-weight: bold;
      color:#c7c7c7;
    }
    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: center;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
    }
    """)
    self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
    self.setWindowModality(Qt.ApplicationModal)
    self.units = "kg" if self.db_wrapper.fetch_local_column("Users", "units") == "metric" else "lb"
    self.setWindowTitle("Lift History")
    
    widget = QWidget()
    self.layout = QFormLayout(widget)
    
    self.setWidget(widget)
    self.setWidgetResizable(True)
    self.create_history(True, True)

  @pyqtSlot(bool)
  def create_history(self, create, init_layout=False):
    exercise_label = QLabel("Exercise")
    exercise_label.setAlignment(Qt.AlignCenter)
    delete_label = QLabel("Delete")
    delete_label.setAlignment(Qt.AlignCenter)

    helper_layout = QFormLayout()
    
    helper_layout.addRow(exercise_label, delete_label)

    self.lift_history = self.db_wrapper.fetch_local_column(self.table_name, "lift_history")
    if create and not self.lift_history == None:
      if not init_layout:
        if not self.db_wrapper.connection_exists: return
        self.delete_history()
      lift_history = json.loads(self.lift_history)
      self.labels = [None] * len(lift_history)
      self.delete_buttons = [None] * len(lift_history)

      for i in range(len(lift_history)):
        self.labels[i] = QLabel(self)
        self.delete_buttons[i] = QPushButton("X", self)
      
      for j, exercise in enumerate(lift_history):
        try:
          self.labels[j].setText(": ".join([exercise[0], " ".join([exercise[1], self.units])]))
        except TypeError: # joining lift for reps as 1RM lift 
          self.labels[j].setText(": ".join([exercise[0], " ".join(["x".join(exercise[1]), self.units])]))
        
        self.delete_buttons[j].setProperty("entry_index", exercise[-1])
        self.delete_buttons[j].clicked.connect(partial(self.delete_history_entry_from_layout, j, self.delete_buttons[j].property("entry_index")))
        
        helper_layout.addRow(self.labels[j], self.delete_buttons[j])

    scroll_area = QScrollArea()
    scroll_area.setContentsMargins(3, 3, 3, 3)
    scroll_area.setWidgetResizable(True)
    helper_widget = QWidget()
    helper_widget.setLayout(helper_layout)
    scroll_area.setWidget(helper_widget)
    self.layout.addRow(scroll_area)

    close_button = QPushButton("Close")
    close_button.clicked.connect(lambda:self.close())
    self.layout.addRow(close_button)

  def delete_history(self):
    for i in reversed(range(self.layout.count())):
      self.layout.itemAt(i).widget().setParent(None)
  
  def delete_history_entry_from_layout(self, i, entry_index):
    self.labels[i].setParent(None)
    self.delete_buttons[i].setParent(None)
    history = json.loads(self.db_wrapper.fetch_local_column(self.table_name, "lift_history"))
    lift_history = [lift for lift in history if not lift[-1] == entry_index]
    if len(lift_history) == 0: lift_history = None
    else: lift_history = json.dumps(lift_history)
    self.db_wrapper.update_table_column(self.table_name, "lift_history", lift_history, True)
Example #28
0
class Update1RMWindow(QWidget):
  change_1RM_lifts_signal = pyqtSignal(bool)
  history_signal = pyqtSignal(bool)
  update_graph_signal = pyqtSignal(bool)

  def __init__(self):
    super().__init__()
    self.db_wrapper = DatabaseWrapper()
    self.table_name = "Compound Exercises"
    self.setStyleSheet("""
    QWidget{
      background-color: #232120;
      font-weight: bold;
      color:#c7c7c7;
    }
    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: center;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
    }
    """)
    self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
    self.setWindowModality(Qt.ApplicationModal)
    self.current_year = str(datetime.now().year)
    self.units = "kg" if self.db_wrapper.fetch_local_column("Users", "units") == "metric" else "lb"
    self.preferred_lifts = json.loads(self.db_wrapper.fetch_local_column(self.table_name, "preferred_lifts"))
    self.setWindowTitle("Update One Rep Max Lifts")
    self.setLayout(self.create_panel())
    self.set_line_edit_values()

  def create_panel(self):
    form_layout = QFormLayout()

    exercise_label = QLabel("Exercise")
    weight_label = QLabel("Weight")
    
    horizontal_press_label = QLabel(self.preferred_lifts["Horizontal Press"])
    self.horizontal_press_edit = QLineEdit()
    self.horizontal_press_edit.setValidator(QIntValidator())

    units_label = QLabel(self.units)
    hbox = QHBoxLayout()
    hbox.addWidget(self.horizontal_press_edit)
    hbox.addWidget(units_label)

    floor_pull_label = QLabel(self.preferred_lifts["Floor Pull"])
    self.floor_pull_edit = QLineEdit()
    self.floor_pull_edit.setValidator(QIntValidator())
    
    units_label1 = QLabel(self.units)
    hbox1 = QHBoxLayout()
    hbox1.addWidget(self.floor_pull_edit)
    hbox1.addWidget(units_label1)

    squat_label = QLabel(self.preferred_lifts["Squat"])
    self.squat_edit = QLineEdit()
    self.squat_edit.setValidator(QIntValidator())
    
    units_label2 = QLabel(self.units)
    hbox2 = QHBoxLayout()
    hbox2.addWidget(self.squat_edit)
    hbox2.addWidget(units_label2)

    vertical_press_label = QLabel(self.preferred_lifts["Vertical Press"])
    self.vertical_press_edit = QLineEdit()
    self.vertical_press_edit.setValidator(QIntValidator())
    
    units_label3 = QLabel(self.units)
    hbox3 = QHBoxLayout()
    hbox3.addWidget(self.vertical_press_edit)
    hbox3.addWidget(units_label3)
    
    buttons_layout = QHBoxLayout()
    save_button = QPushButton("Save")
    save_button.clicked.connect(lambda: self.save_1RM_lifts())
    cancel_button = QPushButton("Cancel")
    cancel_button.clicked.connect(lambda: self.close_update_1RM())
    buttons_layout.addWidget(save_button)
    buttons_layout.addWidget(cancel_button)
    
    form_layout.addRow(exercise_label, weight_label)
    form_layout.addRow(horizontal_press_label, hbox)
    form_layout.addRow(floor_pull_label, hbox1)
    form_layout.addRow(squat_label, hbox2)
    form_layout.addRow(vertical_press_label, hbox3)
    
    main_layout = QVBoxLayout()
    main_layout.addLayout(form_layout)
    main_layout.addLayout(buttons_layout)
    
    return main_layout
  
  def save_1RM_lifts(self):
    try:
      fetched_rep_maxes = json.loads(self.db_wrapper.fetch_local_column(self.table_name, "one_rep_maxes"))
      exercises = list(fetched_rep_maxes.keys())
      horizontal_press_max = str(float(self.horizontal_press_edit.text()))
      floor_pull_max = str(float(self.floor_pull_edit.text()))
      squat_max = str(float(self.squat_edit.text()))
      vertical_press_max = str(float(self.vertical_press_edit.text()))
      new_maxes = {exercises[0]:horizontal_press_max, exercises[1]:floor_pull_max,
                   exercises[2]:squat_max, exercises[3]:vertical_press_max}
      
      diff = self.lift_difference(new_maxes, fetched_rep_maxes, one_RM=True)
      
      self.db_wrapper.update_table_column(self.table_name, "lift_history", diff) 
      self.history_signal.emit(True)
      
      self.db_wrapper.update_table_column(self.table_name, "one_rep_maxes", new_maxes) 
      self.update_one_rep_maxes_history(diff, self.current_year)
      
      self.update_graph_signal.emit(True)
      self.change_1RM_lifts_signal.emit(True)
      
      self.set_line_edit_values()
      self.close() 
    except ValueError: # user submitted text/empty string
      pass
  
  def close_update_1RM(self):
    self.close()
    self.set_line_edit_values()

  def set_line_edit_values(self):
    one_rep_maxes = list(json.loads(self.db_wrapper.fetch_local_column(self.table_name, "one_rep_maxes")).values())
    self.horizontal_press_edit.setText(one_rep_maxes[0])
    self.floor_pull_edit.setText(one_rep_maxes[1])
    self.squat_edit.setText(one_rep_maxes[2])
    self.vertical_press_edit.setText(one_rep_maxes[3])

  def sort_exercises(self, exercise):
    if exercise in ["Bench Press", "Incline Bench Press"]: return 4
    elif exercise in ["Deadlift", "Sumo Deadlift"]: return 3
    elif exercise in ["Back Squat", "Front Squat"]: return 2
    elif exercise in ["Overhead Press", "Push Press"]: return 1 

  # returns sorted dictionary containing updated lifts
  def lift_difference(self, new_lifts, old_lifts, one_RM=False, lifts_reps=False):
    difference = None
    if one_RM:
      db_lifts = set(": ".join([exercise, weight]) for exercise, weight in old_lifts.items())
      new_lifts = set(": ".join([exercise, weight]) for exercise, weight in new_lifts.items() if not weight == '0.0')
      diff = list(new_lifts.difference(db_lifts)) # local lifts that are not in db
      difference = {exercise.split(": ")[0]:exercise.split(": ")[1] for exercise in diff}
    elif lifts_reps:
      db_lifts = set(":".join([exercise, "x".join(values)]) for exercise, values in old_lifts.items())
      new_lifts = set(":".join([exercise, "x".join(values)]) for exercise, values in new_lifts.items() if not values[1] == '0.0')
      diff = list(new_lifts.difference(db_lifts))
      difference = {exercise.split(":")[0]:exercise.split(":")[1].split("x") for exercise in diff}
    return {key: value for key, value in sorted(difference.items(), key=lambda exercise: self.sort_exercises(exercise[0]))}

  def update_one_rep_maxes_history(self, diff, year):
    rm_history = json.loads(self.db_wrapper.fetch_local_column(self.table_name, "rm_history"))
    default_exercises = {"Horizontal Press": "Bench Press", "Floor Pull": "Deadlift",
                         "Squat": "Back Squat", "Vertical Press": "Overhead Press"}
    secondary_exercises = {"Horizontal Press": "Incline Bench Press", "Floor Pull": "Sumo Deadlift",
                           "Squat": "Front Squat", "Vertical Press": "Push Press"} 
    exercises = {}

    for default in default_exercises:
      if not default in exercises: exercises[default] = []
      exercises[default].append(default_exercises[default])

    for secondary in secondary_exercises:
      exercises[secondary].append(secondary_exercises[secondary])

    now = datetime.now()
    if year not in rm_history:
      rm_history[year] = {}
      for month in self.db_wrapper.months:
        exercises_dict = {}
        for lift_type in default_exercises:
          exercises_dict[lift_type] = {default_exercises[lift_type]:[]}
        for lift_type in secondary_exercises:
          exercises_dict[lift_type][secondary_exercises[lift_type]] = []
        rm_history[year][month] = exercises_dict 
    
    for i, (lift, weight) in enumerate(diff.items()):
      lift_type = None
      for exercise_type in exercises:
        if lift in exercises[exercise_type]: lift_type = exercise_type
      entry = rm_history[year][self.db_wrapper.months[now.month-1]][lift_type]
      if lift not in entry: entry[lift] = []
      entry[lift].append(weight) 
    
    rm_history = json.dumps(rm_history)
    self.db_wrapper.update_table_column(self.table_name, "rm_history", rm_history)
class EditCardioHistoryEntry(QWidget):
    update_cardio_history_signal = pyqtSignal(bool)

    def __init__(self, cardio_history, date, activity, index):
        super().__init__()
        self.db_wrapper = DatabaseWrapper()
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
        self.setWindowModality(Qt.ApplicationModal)
        self.table_name = "Weight Loss"
        self.cardio_history = cardio_history
        self.date = date
        self.activity = activity
        self.index = index
        self.entry = self.cardio_history[self.date][self.activity][self.index]
        self.setStyleSheet("""
    QWidget{
      background-color: #322d2d;
      font-weight: bold;
      color:#c7c7c7;
    }
    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: center;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
    }
    """)
        self.units = "kg" if self.db_wrapper.fetch_local_column(
            "Users", "units") == "metric" else "lb"
        self.cardio_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "cardio_history"))
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowFlags(Qt.Tool)
        self.setWindowTitle("Edit Cardio History Entry")
        self.create_layout()

    def create_layout(self):
        layout = QVBoxLayout()
        form_layout = QFormLayout()
        activity_parameter_label = QLabel("Activity Parameter")
        value_label = QLabel("Value")

        time_spent_label = QLabel("Time Spent")
        self.time_spent_line_edit = QLineEdit()
        self.time_spent_line_edit.setValidator(QIntValidator())
        self.time_spent_line_edit.setText(self.entry["Time Spent"])

        distance_travelled_label = QLabel("Distance Travelled")
        self.distance_travelled_line_edit = QLineEdit()
        self.distance_travelled_line_edit.setValidator(QIntValidator())
        self.distance_travelled_line_edit.setText(
            self.entry["Distance Travelled"])

        calories_burnt_label = QLabel("Calories Burnt")
        self.calories_burnt_line_edit = QLineEdit()
        self.calories_burnt_line_edit.setValidator(QIntValidator())
        self.calories_burnt_line_edit.setText(self.entry["Calories Burnt"])

        buttons_layout = QHBoxLayout()
        save_button = QPushButton("Save")
        save_button.clicked.connect(lambda: self.save_entry())
        cancel_button = QPushButton("Cancel")
        cancel_button.clicked.connect(lambda: self.close())
        buttons_layout.addWidget(save_button)
        buttons_layout.addWidget(cancel_button)

        form_layout.addRow(activity_parameter_label, value_label)
        form_layout.addRow(time_spent_label, self.time_spent_line_edit)
        form_layout.addRow(distance_travelled_label,
                           self.distance_travelled_line_edit)
        form_layout.addRow(calories_burnt_label, self.calories_burnt_line_edit)

        layout.addLayout(form_layout)
        layout.addLayout(buttons_layout)
        self.setLayout(layout)

    def save_entry(self):
        self.date = datetime.today().strftime("%d/%m/%Y")
        new_activity_entry = {
            "Time Spent": str(self.time_spent_line_edit.text()),
            "Distance Travelled":
            str(self.distance_travelled_line_edit.text()),
            "Calories Burnt": str(self.calories_burnt_line_edit.text())
        }

        self.cardio_history[self.date][self.activity][
            self.index] = new_activity_entry
        current_cardio_history = json.dumps(self.cardio_history)
        self.db_wrapper.update_table_column(self.table_name, "cardio_history",
                                            current_cardio_history)
        self.update_cardio_history_signal.emit(True)
        self.close()
class CardioHistory(QScrollArea):
    refresh_cardio_labels_signal = pyqtSignal(bool)

    def __init__(self):
        super().__init__()
        self.db_wrapper = DatabaseWrapper()
        self.table_name = "Weight Loss"
        self.setStyleSheet("""
    QWidget{
      background-color: #232120;
      font-weight: bold;
      color:#c7c7c7;
    }
    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: center;
      padding-left: 5%;
      font-family: Montserrat;
    }
    QPushButton:hover:!pressed{
      border: 2px solid;
      border-color: #747474;
    }
    QPushButton:pressed{
      border: 2px solid;
      background-color: #323232;
    }
    """)
        self.units = "kg" if self.db_wrapper.fetch_local_column(
            "Users", "units") == "metric" else "lb"
        self.cardio_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "cardio_history"))
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowTitle("Cardio History")

        widget = QWidget()
        self.layout = QGridLayout(widget)
        self.setWidget(widget)
        self.setWidgetResizable(True)

        self.entry_count = 0
        for date in self.cardio_history:
            for activity in self.cardio_history[date]:
                self.entry_count += len(self.cardio_history[date][activity])
        self.create_history(True, True)

    @pyqtSlot(bool)
    def create_history(self, create, init_layout=False):
        if create:
            if not init_layout:
                self.refresh_cardio_labels_signal.emit(True)
                self.delete_history()

            date_label = QLabel("Date")
            date_label.setAlignment(Qt.AlignCenter)
            activity_label = QLabel("Activity")
            activity_label.setAlignment(Qt.AlignCenter)

            edit_label = QLabel("Edit")
            edit_label.setAlignment(Qt.AlignCenter)
            delete_label = QLabel("Delete")
            delete_label.setAlignment(Qt.AlignCenter)

            helper_layout = QGridLayout()

            helper_layout.addWidget(date_label, 0, 0)
            helper_layout.addWidget(activity_label, 0, 1)
            helper_layout.addWidget(edit_label, 0, 2)
            helper_layout.addWidget(delete_label, 0, 3)

            self.date_labels = [None] * self.entry_count
            self.cardio_labels = [None] * self.entry_count
            self.edit_buttons = [None] * self.entry_count
            self.delete_buttons = [None] * self.entry_count

            for i in range(self.entry_count):
                self.date_labels[i] = QLabel(self)
                self.cardio_labels[i] = QLabel(self)
                self.edit_buttons[i] = QPushButton("Edit", self)
                self.delete_buttons[i] = QPushButton("X", self)

            row = 1
            j = 0
            for date in reversed(list(self.cardio_history.keys())):
                for activity in self.cardio_history[date]:
                    if len(self.cardio_history[date][activity]) > 0:
                        for data_index, activity_data in enumerate(
                                list(
                                    reversed(
                                        self.cardio_history[date][activity]))):
                            self.cardio_labels[j].setText(activity)
                            self.date_labels[j].setText(date)
                            self.edit_buttons[j].setProperty(
                                "data_index", data_index)
                            self.edit_buttons[j].clicked.connect(
                                partial(
                                    self.edit_cardio_dialog, date, activity,
                                    self.edit_buttons[j].property(
                                        "data_index")))
                            self.delete_buttons[j].setProperty(
                                "data_index", data_index)
                            self.delete_buttons[j].clicked.connect(
                                partial(
                                    self.delete_entry, j, date, activity,
                                    self.edit_buttons[j].property(
                                        "data_index")))

                            helper_layout.addWidget(self.date_labels[j], row,
                                                    0, 1, 1)
                            helper_layout.addWidget(self.cardio_labels[j], row,
                                                    1, 1, 1)
                            helper_layout.addWidget(self.edit_buttons[j], row,
                                                    2, 1, 1)
                            helper_layout.addWidget(self.delete_buttons[j],
                                                    row, 3, 1, 1)
                            j += 1
                            row += 1

        scroll_area = QScrollArea()
        scroll_area.setContentsMargins(3, 3, 3, 3)
        scroll_area.setWidgetResizable(True)
        helper_widget = QWidget()
        helper_widget.setLayout(helper_layout)
        scroll_area.setWidget(helper_widget)
        self.layout.addWidget(scroll_area, 0, 0, 1, 1)

        close_button = QPushButton("Close")
        close_button.clicked.connect(lambda: self.close())
        self.layout.addWidget(close_button, row, 0, 1, 4)

    def edit_cardio_dialog(self, date, activity, index):
        self.edit_entry_dialog = EditCardioHistoryEntry(
            self.cardio_history, date, activity, index)
        self.edit_entry_dialog.update_cardio_history_signal.connect(
            lambda signal: self.create_history(signal))
        self.edit_entry_dialog.show()

    def delete_history(self):
        self.cardio_history = json.loads(
            self.db_wrapper.fetch_local_column(self.table_name,
                                               "cardio_history"))
        self.refresh_cardio_labels_signal.emit(True)
        for i in reversed(range(self.layout.count())):
            self.layout.itemAt(i).widget().setParent(None)

    def delete_entry(self, j, date, activity, index):
        self.date_labels[j].setParent(None)
        self.cardio_labels[j].setParent(None)
        self.edit_buttons[j].setParent(None)
        self.delete_buttons[j].setParent(None)
        del self.cardio_history[date][activity][index]
        current_cardio_history = json.dumps(self.cardio_history)
        self.db_wrapper.update_table_column(self.table_name, "cardio_history",
                                            json.dumps(self.cardio_history))