1 /*
2 	SPDX-FileCopyrightText: 2009-2021 Graeme Gott <graeme@gottcode.org>
3 
4 	SPDX-License-Identifier: GPL-3.0-or-later
5 */
6 
7 #ifndef TANGLET_SCORES_DIALOG_H
8 #define TANGLET_SCORES_DIALOG_H
9 
10 #include <QDateTime>
11 #include <QDialog>
12 class QDialogButtonBox;
13 class QGridLayout;
14 class QLabel;
15 class QLineEdit;
16 class QSettings;
17 class QTabWidget;
18 
19 /**
20  * @brief The ScoresDialog class displays the list of high scores.
21  */
22 class ScoresDialog : public QDialog
23 {
24 	Q_OBJECT
25 
26 	/** The columns of each scores page. */
27 	enum Columns
28 	{
29 		RankColumn,
30 		NameColumn,
31 		ScoreColumn,
32 		MaxScoreColumn,
33 		DateColumn,
34 		SizeColumn,
35 		TotalColumns
36 	};
37 
38 	/**
39 	 * @brief The ScoresDialog::Score struct descibres a high score.
40 	 */
41 	struct Score
42 	{
43 		QString name; /**< the player's name */
44 		int score; /**< the value of the score */
45 		int max_score; /**< the maximum score available on the played board */
46 		QDateTime date; /**< when the score was made */
47 		int size; /**< the size of the board */
48 	};
49 
50 	/**
51 	 * @brief The ScoresDialog::Page class contains a page of high scores.
52 	 */
53 	class Page : public QWidget
54 	{
55 	public:
56 		/**
57 		 * Constructs a page of scores.
58 		 * @param timer the time the page represents
59 		 * @param settings where to load the scores from
60 		 * @param parent the QWidget that manages the page
61 		 */
62 		Page(int timer, QSettings& settings, QWidget* parent);
63 
64 		/**
65 		 * @return whether this score page has any scores
66 		 */
isEmpty()67 		bool isEmpty() const
68 		{
69 			return m_scores.isEmpty();
70 		}
71 
72 		/**
73 		 * @return the name of the page, used for the tab titles
74 		 */
75 		QString name() const;
76 
77 		/**
78 		 * Adds a score to the high score board.
79 		 * @param name the player's name
80 		 * @param score the value of the score
81 		 * @param max_score the maximum score available on the played board
82 		 * @param date when the score was made
83 		 * @param size the size of the board
84 		 * @return @c true if the score was added
85 		 */
86 		bool addScore(const QString& name, int score, int max_score, const QDateTime& date, int size);
87 
88 		/**
89 		 * Start editing the player name of the most recent score.
90 		 * @param playername the widget used to edit the player name
91 		 */
92 		void editStart(QLineEdit* playername);
93 
94 		/**
95 		 * The player has finished entering their name and the scores are saved.
96 		 */
97 		void editFinish(QLineEdit* playername);
98 
99 	private:
100 		/**
101 		 * Loads the scores from the settings.
102 		 * @param settings where to load the scores from
103 		 */
104 		void load(QSettings& settings);
105 
106 		/**
107 		 * Sets the text of the high scores. Adds the dashed lines for empty scores.
108 		 */
109 		void updateItems();
110 
111 	private:
112 		const int m_timer; /**< which timer mode this scores page represents */
113 		QList<Score> m_scores; /**< the high score data */
114 		QLabel* m_score_labels[10][TotalColumns]; /**< the grid[row][column] of labels to display the scores */
115 		QGridLayout* m_scores_layout; /**< the layout for the dialog */
116 		int m_row; /**< location of most recently added score */
117 	};
118 
119 public:
120 	/**
121 	 * Constructs a scores dialog.
122 	 * @param parent the QWidget that manages the dialog
123 	 */
124 	explicit ScoresDialog(QWidget* parent = nullptr);
125 
126 	/**
127 	 * Attempts to add a score.
128 	 * @param score the value of the score
129 	 * @param max_score the maximum score available on the played board
130 	 * @return whether the score was added
131 	 */
132 	bool addScore(int score, int max_score);
133 
134 	/**
135 	 * Checks if a score is a high score.
136 	 * @param score the value of the score
137 	 * @param timer the timer mode to check for scores
138 	 * @return whether the score is a high score, and if it is the highest
139 	 */
140 	static int isHighScore(int score, int timer);
141 
142 	/**
143 	 * Converts the stored scores to the new format.
144 	 */
145 	static void migrate();
146 
147 protected:
148 	/**
149 	 * Override hideEvent to add score if the player has not already pressed enter.
150 	 * @param event details of the hide event
151 	 */
152 	void hideEvent(QHideEvent* event) override;
153 
154 	/**
155 	 * Override keyPressEvent to ignore return key. Keeps dialog from closing when the player
156 	 * presses return after entering their name.
157 	 * @param event details of the key press event
158 	 */
159 	void keyPressEvent(QKeyEvent* event) override;
160 
161 private slots:
162 	/**
163 	 * Enters the score and saves list of scores once the player has finished entering their name.
164 	 */
165 	void editingFinished();
166 
167 private:
168 	/**
169 	 * Adds a tab of high scores.
170 	 * @param page the widget containing the scores
171 	 */
172 	void addTab(Page* page);
173 
174 private:
175 	QDialogButtonBox* m_buttons; /**< buttons to control dialog */
176 	QTabWidget* m_tabs; /**< contains the tabs of the pages */
177 	QList<Page*> m_pages; /**< the list of pages of scores */
178 
179 	Page* m_active_page; /**< the page where a new score is being added */
180 	QLineEdit* m_username; /**< widget for the player to enter their name */
181 
182 	QString m_default_name; /**< the default name */
183 
184 	static QVector<int> m_max; /**< the largest high score */
185 	static QVector<int> m_min; /**< the smallest high score */
186 };
187 
188 #endif // TANGLET_SCORES_DIALOG_H
189