Bonjour
Voilà quelques semaines que j'y travaille dessus pendant mon temps libre et j'aimerai que vous me disiez ce que vous en pensez afin de m'améliorer tout en faisant évoluer le code en conséquence. Le code fonctionne ici mais si vous arrivez à le faire planter, je suis preneur

Le programme sert à rentrer des élèves avec leurs notes respectives et en fonction des matières spécifiées.

Il y a 1 point où je suis sur d'avoir des critiques c'est pour le franglais . J'ai commencé à utiliser de l'anglais mais, du fait de ma limitation dans la langue, je suis vite revenu au français

[main.cpp]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
#include <QApplication>
#include "fenetre.h"
 
int main(int argc, char **argv) {
	QApplication app(argc, argv);
 
	Fenetre fenetre;
	fenetre.show();
 
	return app.exec();
}
[eleve.h]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef DEF_ELEVE_H
#define DEF_ELEVE_H
 
#include <QString>
#include <QVector>
 
class Eleve {
	public:
		Eleve(QString nom, QString prenom);
 
		void setNom(QString n_nom);
		void setPrenom(QString n_prenom);
		void addNote(int position, QString n_note);
		void insertColonne();
		void insertColonne(QString note);
		void insertColonne(int position);
		void removeColonne(int position);
		void changeNote(int position, QString n_note);
		void setClassement(int n_classement);
		void clearNote();
 
		QString getNom() const;
		QString getPrenom() const;
		QString getNote(int position) const;
		double getMoyenne();
		int getSize() const;
		int getClassement() const;
		int getNombreNote();
 
	private:
		QString nom;
		QString prenom;
		int classement;
		QVector<QString> tab_note;
 
		void resize(int taille);
};
 
#endif
[eleve.cpp]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "eleve.h"
 
Eleve::Eleve(QString nom, QString prenom) {
	setNom(nom);
	setPrenom(prenom);
	setClassement(-1);
}
 
void Eleve::setNom(QString n_nom) {
	nom = n_nom;
}
 
void Eleve::setPrenom(QString n_prenom) {
	prenom = n_prenom;
}
 
void Eleve::addNote(int position, QString n_note) {
	tab_note.replace(position, n_note);
}
 
void Eleve::insertColonne() {
	tab_note << "";
}
 
void Eleve::insertColonne(QString note) {
	tab_note << note;
}
 
void Eleve::insertColonne(int position) {
	tab_note.insert(position, "");
}
 
void Eleve::removeColonne(int position) {
	tab_note.remove(position);
}
 
void Eleve::changeNote(int position, QString n_note) {
	tab_note.replace(position, n_note);
}
 
void Eleve::setClassement(int n_classement) {
	classement = n_classement;
}
 
void Eleve::clearNote() {
	tab_note.clear();
	resize(0);
}
 
void Eleve::resize(int taille) {
	tab_note.resize(taille);
}
 
QString Eleve::getNom() const {
	return nom;
}
 
QString Eleve::getPrenom() const {
	return prenom;
}
 
QString Eleve::getNote(int position) const {
	return tab_note[position];
}
 
double Eleve::getMoyenne() {
	if(getNombreNote() == 0) {
		return -1;
	}
	else {
		double somme = 0;
		int compteur_note = 0;
		double tmp;
		bool ok;
 
		for(int i = 0; i < getSize(); i++) {
			ok = false;
			tmp = tab_note[i].toDouble(&ok);
			if(ok) {
				somme += tmp;
				compteur_note++;
			}
		}
		return (somme / compteur_note);
	}
}
 
int Eleve::getSize() const {
	return tab_note.size();
}
 
int Eleve::getClassement() const {
	return classement;
}
 
int Eleve::getNombreNote() {
	int compteur_note = 0;
	bool ok;
 
	for(int i = 0; i < getSize(); i++) {
		ok = false;
		tab_note[i].toDouble(&ok);
		if(ok == true) {
			compteur_note++;
		}
	}
 
	return compteur_note;
}
[classe.h]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#ifndef DEF_CLASSE_H
#define DEF_CLASSE_H
 
#include <QVector>
#include <QStringList>
#include "eleve.h"
 
class Classe {
	public:
		void addEleve(Eleve *n_eleve);
		void addEleve(Eleve *n_eleve, int nb_colonne);
		void removeEleve(int position);
		void addColonneAllEleve(int position);
		void removeColonneAllEleve(int position);
		void changeNote(int positionEleve, int position, QString n_note);
		void changeNom(int position, QString n_nom);
		void changePrenom(int position, QString n_prenom);
		void trier();
		void trierParNote();
		void clearAllEleve();
 
 
		int getPosition(Eleve *n_eleve);
		int getSize();
		int getClassement(int position);
		double getMoyenne(int position);
		QString getInfoEleve(int position);
		QStringList getTotalInfoEleve(int position);
 
	private:
		QVector<Eleve*> classe;
};
 
bool insensitiveLessThan(const Eleve *s1, const Eleve *s2);
bool classementPM(Eleve *s1, Eleve *s2);
 
#endif
[classe.cpp]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include "classe.h"
 
void Classe::addEleve(Eleve *n_eleve) {
	classe << n_eleve;
	trier();
}
 
void Classe::addEleve(Eleve *n_eleve, int nb_colonne) {
	int position = getSize();
 
	classe << n_eleve;
	for(int i = 0; i < nb_colonne; i++) {
		classe[position]->insertColonne();
	}
	trier();
}
 
void Classe::removeEleve(int position) {
	classe.remove(position);
}
 
void Classe::addColonneAllEleve(int position) {
	for(int i = 0; i < getSize(); i++) {
		classe[i]->insertColonne(position);
	}
}
 
void Classe::changeNote(int positionEleve, int position, QString n_note) {
	classe[positionEleve]->changeNote(position, n_note);
}
 
void Classe::removeColonneAllEleve(int position) {
	for(int i = 0; i < getSize(); i++) {
		classe[i]->removeColonne(position);
	}
}
 
void Classe::changeNom(int position, QString n_nom) {
	classe[position]->setNom(n_nom);
}
 
void Classe::changePrenom(int position, QString n_prenom) {
	classe[position]->setPrenom(n_prenom);
}
 
void Classe::trier() {
	qSort(classe.begin(), classe.end(), insensitiveLessThan);
}
 
void Classe::trierParNote() {
	qSort(classe.begin(), classe.end(), classementPM);
	for(int i = 0; i < getSize(); i++) {
		classe[i]->setClassement(i + 1);
	}
}
 
void Classe::clearAllEleve() {
	for(int i = 0; i < getSize(); i++) {
		classe[i]->clearNote();
	}
	classe.clear();
}
 
int Classe::getPosition(Eleve *n_eleve) {
	for(int i = 0; i < getSize(); i++) {
		if((classe[i]->getNom() == n_eleve->getNom()) && (classe[i]->getPrenom() == n_eleve->getPrenom()))
			return i;
	}
	return -1;
}
 
int Classe::getSize() {
	return classe.size();
}
 
int Classe::getClassement(int position) {
	return classe[position]->getClassement();
}
 
double Classe::getMoyenne(int position) {
	return classe[position]->getMoyenne();
}
 
QString Classe::getInfoEleve(int position) {
	QStringList info;
 
	info << classe[position]->getNom() << classe[position]->getPrenom();
	if(classe[position]->getSize() > 0) {
		for(int i = 0; i < classe[position]->getSize(); i++) {
			info << classe[position]->getNote(i);
		}
	}
 
	return info.join(":");
}
 
QStringList Classe::getTotalInfoEleve(int position) {
	QStringList info;
 
	info << classe[position]->getNom() << classe[position]->getPrenom();
	if(classe[position]->getClassement() == -1)
		info << "";
	else {
		info << QString::number(classe[position]->getClassement());
		info << QString::number(classe[position]->getMoyenne());
		for(int i = 0; i < classe[position]->getSize(); i++) {
			info << classe[position]->getNote(i);
		}
	}
 
	return info;
}
 
bool insensitiveLessThan(const Eleve *s1, const Eleve *s2) {
	if(s1->getNom().toLower() == s2->getNom().toLower())
		return s1->getPrenom().toLower() < s2->getPrenom().toLower();
	else
		return s1->getNom().toLower() < s2->getNom().toLower();
}
 
bool classementPM(Eleve *s1, Eleve *s2) {
	return s1->getMoyenne() > s2->getMoyenne();
}
[fenetre.h]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef DEF_FENETRE_H
#define DEF_FENETRE_H
 
#include <QtGui>
 
#include "ui_gui.h"
#include "classe.h"
 
class Fenetre : public QMainWindow, private Ui::MainWindow {
	Q_OBJECT
 
	public:
		Fenetre(QMainWindow *parent = 0);
 
	private slots:
		void nouveau();
		void ajouterColonne();
		void insererColonne();
		void supprimerColonne();
		void ajouterEleve();
		void supprimerEleve();
		void aPropos();
		void enregistrerSous();
		void enregistrer();
		void ouvrir();
		void imprimer();
		void action(QStandardItem *objet);
 
	private:
		QStandardItemModel *modele;
		QStringList listeHeader;
		QStringList listeHeaderFollow;
		QString nomFichier;
		Classe groupe;
 
		void funcPrivateSav();
		void chargerTableDansModele();
		void majPremierCaractere(QString &mot);
};
 
#endif
[fenetre.cpp]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
#include "fenetre.h"
#include "classe.h"
 
Fenetre::Fenetre(QMainWindow *parent) : QMainWindow(parent) {
	// Chargement de la fenêtre vu que j'utilise QtDesigner
	setupUi(this);
 
	// On définit le nouveau modèle avec aucune ligne et 4 colonnes de base
	modele = new QStandardItemModel(0,4, this);
 
	// Création des titres principaux
	listeHeader << QString::fromUtf8("Nom") << QString::fromUtf8("Prénom")
							<< QString::fromUtf8("Classement") << QString::fromUtf8("Moyenne");
 
	// On place la liste des titres dans le tableau
	modele->setHorizontalHeaderLabels(listeHeader);
 
	// On définit le modèle à afficher
	tableView->setModel(modele);
 
	// Gestion des action des menus
	connect(actionNouveau, SIGNAL(triggered()), this, SLOT(nouveau()));
	connect(actionAjouter_une_colonne, SIGNAL(triggered()), this, SLOT(ajouterColonne()));
	connect(actionSupprimer_une_colonne,SIGNAL(triggered()), this, SLOT(supprimerColonne()));
	connect(actionAjouter_un_eleve, SIGNAL(triggered()), this, SLOT(ajouterEleve()));
	connect(actionSupprimer_un_eleve, SIGNAL(triggered()), this, SLOT(supprimerEleve()));
	connect(action_propos, SIGNAL(triggered()), this, SLOT(aPropos()));
	connect(actionEnregistrer_sous, SIGNAL(triggered()), this, SLOT(enregistrerSous()));
	connect(actionEnregistrer, SIGNAL(triggered()), this, SLOT(enregistrer()));
	connect(actionOuvrir, SIGNAL(triggered()), this, SLOT(ouvrir()));
	connect(actionImprimer, SIGNAL(triggered()), this, SLOT(imprimer()));
	// Dès qu'une case du modèle est modifier on exécute le signal suivant pour intercepter la modification
	connect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
}
 
void Fenetre::nouveau() {
	// On vérifie que le groupe est bien vide. Si ce n'est pas le cas, on le vide avant de passer à la suite
	if(groupe.getSize() != 0) {
		groupe.clearAllEleve();
	}
 
	// On efface l'affichage au cas où il y aurait un ou des éléments dans les cellules
	modele->clear();
 
	// On affiche les titres d'origines
	modele->setHorizontalHeaderLabels(listeHeader);
 
	// On vide la liste des titres des nouvelles colonnes au cas où il y ai des choses dedans
	if(!listeHeaderFollow.isEmpty()) {
		listeHeaderFollow.clear();
	}
 
	// Désactiver le bouton enregistrer dans le menu Fichier
	if(actionEnregistrer->isEnabled()) {
		actionEnregistrer->setEnabled(false);
	}
 }
 
void Fenetre::ajouterColonne() {
	// Permet de savoir si l'utilisateur à cliquer sur le bouton ok ou non
	bool ok = false;
	int numColonne = modele->columnCount();
 
	QString nomColonne = QInputDialog::getText(this, "Nom", "Nom de la colonne :", QLineEdit::Normal, QString(), &ok);
 
	// Si ok est vrai et qu'un nom est inséré, on crée la nouvelle colonne avec le nom inséré
	if(ok && !nomColonne.isEmpty()) {
		// On met l'intégralité du mot en minuscule
		nomColonne = nomColonne.toLower();
		// On met la première lettre du nom de la colonne en majuscule
		nomColonne.replace(0, 1, nomColonne[0].toUpper());
 
		// On rajoute la colonne sur le modèle
		modele->insertColumn(numColonne);
		// On change son titre
		modele->setHeaderData(numColonne, Qt::Horizontal, nomColonne);
		// On insère le nouveau titre dans une liste
		listeHeaderFollow << nomColonne;
		// On ajoute une colonne à tous les élèves
		groupe.addColonneAllEleve(numColonne - 4);
	}
	// Si ok est vrai mais qu'auncun nom ne soit inséré, on crée la nouvelle colonne en utilisant le nom par défaut
	else if(ok && nomColonne.isEmpty()) {
		// On ajoute la colonne sur le modèle
		modele->insertColumn(numColonne);
		// On insère le titre dans une liste
		listeHeaderFollow << QString::number(numColonne);
		// On ajoute une colonne à tous les élèves
		groupe.addColonneAllEleve(numColonne - 4);
	}
	// Si l'utilisateur clique sur annuler, on ne fait rien
}
 
void Fenetre::insererColonne() {
	// Amélioration
}
 
void Fenetre::supprimerColonne() {
	// Liste qui servira à stocker les numéros de colonnes à supprimer
	QList<int> listeColonne;
	// On récupère la liste des colonnes sélectionner pour la suppression
	QModelIndexList liste = tableView->selectionModel()->selectedIndexes();
 
	for(int i = 0; i < liste.size(); i++) {
		// Si les colonnes sélectionnées sont inférieures à 4 (nom, prénom, classement, moyenne qui ne doivent pas être supprimées), on ne fait rien
		if(liste[i].column() < 4)
			continue;
		// Si le numéro de la colonne est déjà présent dans la liste, on ne fait rien pour éviter les doublons
		else if(listeColonne.contains(liste[i].column()))
			continue;
		// Si les conditions précédentes ne sont pas remplis, alors on ajoute le numéro de la colonne dans la liste
		listeColonne << liste[i].column();
	}
 
	// On trie la liste par ordre croissant
	qSort(listeColonne.begin(), listeColonne.end());
 
	// On supprime les colonnes en commençant par la fin
	for(int i = listeColonne.size() - 1; i >= 0; i--) {
		// On supprime le ou les titres. On soustrait -4 pour faire le décalage avec les 4 premières colonnes
		listeHeaderFollow.removeAt(listeColonne[i] - 4);
		// On supprime la colonne
		modele->removeColumn(listeColonne[i]);
		// On supprime la colonne sur tous les élèves. On soustrait -4 pour faire le décalage avec les 4 premières colonnes
		groupe.removeColonneAllEleve(listeColonne[i] - 4);
 
		// On trie les élèves par notes puisqu'il y a peut-être eu une modification des moyennes donc du classement
		groupe.trierParNote();
		// On trie les élèves par ordre alpha pour les remettre correctement
		groupe.trier();
		// Afficher les moyennes de tous les élèves
		for(int i = 0; i < groupe.getSize(); i++) {
			modele->setItem(i, 3, new QStandardItem(QString::number(groupe.getMoyenne(i))));
		}
		// Afficher le classement de tous les élèves
		for(int i = 0; i < groupe.getSize(); i++) {
			modele->setItem(i, 2, new QStandardItem(QString::number(groupe.getClassement(i))));
		}
	}
}
 
void Fenetre::ajouterEleve() {
	bool ok_nom, ok_prenom;
	QString nom, prenom;
 
	// On demande de saisir le nom
	nom = QInputDialog::getText(this, QString::fromUtf8("Nom de l'élève"), QString::fromUtf8("Entrez le nom de l'élève :"), QLineEdit::Normal, QString(), &ok_nom);
 
	// Si l'utilisateur clique sur annuler, on s'arrête
	if(ok_nom) {
		// On demande de saisir le prénom
		prenom = QInputDialog::getText(this, QString::fromUtf8("Prénom de l'élève"), QString::fromUtf8("Entrez le prénom de l'élève :"), QLineEdit::Normal, QString(), &ok_prenom);
	}
 
	if(ok_nom && ok_prenom && !nom.isEmpty() && !prenom.isEmpty()) {
		// On désactive le signal qui détecte la modification d'une des cellules
		disconnect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
 
		// On met la première lettre du nom et du prénom en majuscule
		majPremierCaractere(nom);
		majPremierCaractere(prenom);
 
		// On ajoute l'élève dans le groupe en prenant soin de créer le nombre de colonne existantes en son sein
		groupe.addEleve(new Eleve(nom, prenom), listeHeaderFollow.size());
 
		// Recharger l'intégralité de la table
		chargerTableDansModele();
 
		// On réactive le signal pour détecter les modifications futures et potentiels d'une des cellules
		connect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
	}
}
 
void Fenetre::supprimerEleve() {
	// Cette variable permet de savoir quels sont la ou les lignes qui seront supprimées
	QList<int> listeLigne;
	// Cette variable permet de savoir quels sont la ou les lignes qui sélectionnées
	QModelIndexList liste = tableView->selectionModel()->selectedIndexes();
 
	// On parcourt la liste des lignes sélectionnées
	for(int i = 0; i < liste.size(); i++) {
		// Si la ligne est déjà présente, on continue pour éviter un doublon
		if(listeLigne.contains(liste[i].row()))
			continue;
		// Autrement on ajoute la ligne à la liste
		listeLigne << liste[i].row();
	}
 
	// On trie la liste des lignes à supprimer
	qSort(listeLigne.begin(), listeLigne.end());
 
	// On supprime les lignes en commençant par la fin
	for(int i = listeLigne.size() - 1; i >= 0; i--) {
		// On supprime la ligne
		modele->removeRow(listeLigne[i]);
		// On supprime l'élève du groupe
		groupe.removeEleve(listeLigne[i]);
	}
 
	// On actualise le classement du groupe
	groupe.trierParNote();
 
	// On classe par ordre alphabétique
	groupe.trier();
 
	// On affiche le nouveau classement de tous les élèves restant
	for(int i = 0; i < groupe.getSize(); i++) {
		modele->setItem(i, 2, new QStandardItem(QString::number(groupe.getClassement(i))));
	}
}
 
void Fenetre::aPropos() {
	//////////////////////
	// Faire cette méthode
	//////////////////////
}
 
void Fenetre::enregistrerSous() {
	// On appelle la fenêtre de dialogue permettant de spécifier le fichier pour enregistrer
	nomFichier = QFileDialog::getSaveFileName(this, QString::fromUtf8("Sélectionner un fichier"), QString(), "Fichiers *.txt;;Tous les fichier *");
 
	//////////////////////////////////////////////////////////////////////////////////////////
	// Vérifier que l'extension donnée en fin de fichier est bien respectée sinon, la rajouter
	//////////////////////////////////////////////////////////////////////////////////////////
 
	funcPrivateSav();
}
 
void Fenetre::enregistrer() {
	funcPrivateSav();
}
 
void Fenetre::ouvrir() {
	// On sauvegarde l'ancien emplacement du fichier s'il existait
	QString nomFichierSav = nomFichier;
 
	// On appelle la fenêtre de dialogue permettant de spécifier le fichier à charger
	nomFichier = QFileDialog::getOpenFileName(this, QString::fromUtf8("Sélectionner un fichier"), QString(), "Fichiers *.txt;;Tous les fichier *");
	if(nomFichier.isEmpty()) {
		// On recharge le nom du fichier sauvegarder (s'il existait)
		nomFichier = nomFichierSav;
	}
	else {
		QFile fichier(nomFichier);
		if(fichier.open(QIODevice::ReadOnly | QIODevice::Text)) {
			// On efface tous les élèves pouvant être présent dans le groupe si jamais il a été utilisé
			groupe.clearAllEleve();
 
			// On efface les colonnes si de nouvelles avaient été créées
			listeHeaderFollow.clear();
 
			// On efface le modele actuel
			modele->clear();
 
			// On charge le fichier
			int compteur = 0;
			QString texte;
			QStringList data;
			QTextStream flux(&fichier);
 
			// Tant qu'on est pas arrivé à la fin du fichier, on continu à lire ligne par ligne
			while(!flux.atEnd()) {
				texte = flux.readLine();
				if(compteur == 0) {
					// La première ligne du fichier contient les noms des colonnes supplémentaires
					listeHeaderFollow = texte.split(":");
					compteur++;
				}
				else {
					// Pour chaque nouvelle ligne lu, on découpe les éléments pour créer un nouvel élève
					data = texte.split(":");
					Eleve *eleve = new Eleve(data[0], data[1]);
					for(int i = 2; i < data.size(); i++) {	
						eleve->insertColonne(data[i]);
					}
					// On ajoute le nouvel élève au groupe
					groupe.addEleve(eleve);
				}
			}
			// On ferme le fichier une fois lu complètement
			fichier.close();
 
			// On trie les élèves par notes
			groupe.trierParNote();
 
			// On les trie à nouveau par ordre alphabétique
			groupe.trier();
 
			// Déconnexion du signal itemChanged
			disconnect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
 
			// On affiche toutes les colonnes après avoir lu le fichier
			modele->setHorizontalHeaderLabels(listeHeader + listeHeaderFollow);
 
			// On affiche les informations concernant l'élève dans le modèle
			chargerTableDansModele();
 
			// Activer la partie enregistrer dans le menu si celui-ci n'est pas encore activé
			if(!actionEnregistrer->isEnabled()) {
				actionEnregistrer->setEnabled(true);
			}
 
			// Reconnection du signal itemChanged
			connect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
		}
		else {
			// Si on ne peut pas charger les infos du fichier, on affiche un message d'erreur
			QMessageBox::critical(this, "Erreur", "Impossible de charger les informations du fichier " + nomFichier);
		}
	}
}
 
void Fenetre::imprimer() {
/*	QPrinter *printer = new QPrinter(QPrinter::HighResolution);
	printer->setPaperSize (QPrinter::A4);
	printer->setOutputFormat (QPrinter::PdfFormat);    
	printer->setOrientation(QPrinter::Portrait);
	printer->setFullPage(true);
 
	QPrintDialog printDialog(printer, this);
	if ( printDialog.exec() == 1) {
	}
*/
}
 
void Fenetre::action(QStandardItem *objet) {
	// Si la cellule modifiée est la 1ière colonne alors, on va modifier le nom de la personne
	if(objet->column() == 0) {
		QString nom = objet->text();
		// On met en majuscule la première lettre de chaque mot
		majPremierCaractere(nom);
		// Si il y a modification, on réaffiche correctement le nom
		if(nom != objet->text()) {
			// On désactive l'action associée à la modification de la cellule
			disconnect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
			// On modifie la cellule
			objet->setText(nom);
			// On réactive l'action associée à la modification de la cellule
			connect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
		}
 
		// On change le nom de l'élève au niveau du groupe
		groupe.changeNom(objet->row(), nom);
	}
 
	// Si la cellule modifiée est la 2ième colonne alors, on va modifier le prénom de la personne
	else if(objet->column() == 1) {
		QString prenom = objet->text();
		// On met en majuscule la première lettre de chaque mot
		majPremierCaractere(prenom);
 
		// Si il y a modification, on réaffiche correctement le nom
		if(prenom != objet->text()) {
			// On désactive l'action associée à la modification de la cellule
			disconnect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
			// On modifie la cellule
			objet->setText(prenom);
			// On réactive l'action associée à la modification de la cellule
			connect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
		}
 
		// On change le prénom de l'élève au niveau du groupe
		groupe.changePrenom(objet->row(), prenom);
	}
 
	if(objet->column() > 3) {
		QString texte = objet->text();
		double note;
		bool ok;
 
		note = texte.toDouble(&ok);
		if(ok) {
			// C'est un chiffre
			if(note >= 0 && note <= 20) {
				// Ajouter la note
				groupe.changeNote(objet->row(), objet->column() - 4, objet->text());
				// Modifier la moyenne
				modele->setItem(objet->row(), 3, new QStandardItem(QString::number(groupe.getMoyenne(objet->row()))));
				// Recalculer les classements
				groupe.trierParNote();
				// Reclasser les élèves par ordre Alpha
				groupe.trier();
				// Réafficher tous les classements
				for(int i = 0; i < groupe.getSize(); i++) {
					modele->setItem(i, 2, new QStandardItem(QString::number(groupe.getClassement(i))));
				}
			}
			else {
				// Déconnexion du signal itemChanged
				disconnect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
 
				// Effacer le chiffre
				objet->setText("");
 
				// Afficher un message d'information pour dire que le chiffre doit être compris entre 0 et 20
				QMessageBox::warning(this, QString::fromUtf8("Avertissement"), QString::fromUtf8("La note doit être comprise entre 0 et 20 inclus"));
 
				// Reconnection du signal itemChanged
				connect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
			}
		}
		else {
			if(texte.isEmpty()) {
				groupe.changeNote(objet->row(), objet->column() - 4, "");
			}
			// Ce n'est pas un chiffre
			else if(texte == "Abs") {
				groupe.changeNote(objet->row(), objet->column() - 4, texte);
			}
			else if(texte.toLower() == "abs") {
				// Déconnexion du signal itemChanged
				disconnect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
 
				objet->setText("Abs");
				groupe.changeNote(objet->row(), objet->column() - 4, texte);
 
				// Reconnection du signal itemChanged
				connect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
			}
			else {
				// Déconnexion du signal itemChanged
				disconnect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
 
				// On efface la donnée dans la cellule
				objet->setText(QString(""));
 
				// On affiche un message d'information pour dire que l'entrée ne correspondant à rien
				QMessageBox::critical(this, QString::fromUtf8("Avertissement"), QString::fromUtf8("La chaine doit être soit un nombre compris entre 0 et 20 soit être Abs"));
 
				// Reconnection du signal itemChanged
				connect(modele, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(action(QStandardItem*)));
			}
		}
	}
}
 
void Fenetre::funcPrivateSav() {
	// Si le nom du fichier n'est pas vide alors, on va l'ouvrir pour écrire les données dedans
	if(!nomFichier.isEmpty()) {
		QFile fichier(nomFichier);
		if(fichier.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
			QTextStream flux(&fichier);
 
			// On enregistre les titres des colonnes sur la ligne 1
			flux << listeHeaderFollow.join(":") << "\n";
 
			// On trie les élèves par ordre alpha
			groupe.trier();
 
			// Enregistrer toutes les infos élèves
			for(int i = 0; i < groupe.getSize(); i++) {
				flux << groupe.getInfoEleve(i) << "\n";
			}
 
			// On ferme le fichier
			fichier.close();
 
			// Activer la partie enregistrer dans le menu
			if(!actionEnregistrer->isEnabled()) {
				actionEnregistrer->setEnabled(true);
			}
		}
		else {
			// On affiche un message si on ne peut pas enregistrer dans le fichier spécifié
			QMessageBox::critical(this, "Erreur", "Impossible d'enregistrer les informations dans " + nomFichier);
		}
	}
}
 
 
// Cette fonction permet de charger les données sur le modèle
void Fenetre::chargerTableDansModele() {
	modele->clear();
 
	modele->setHorizontalHeaderLabels(listeHeader + listeHeaderFollow);
 
	for(int i = 0; i < groupe.getSize(); i++) {
		QStringList info = groupe.getTotalInfoEleve(i);
 
		for(int j = 0; j < info.size(); j++) {
			modele->setItem(i, j, new QStandardItem(info.at(j)));
		}
	}
}
 
// Cette fonction permet de mettre la première lettre de chaque mot en majuscule
void Fenetre::majPremierCaractere(QString& mot) {
	QStringList listeMot, listeBis;
 
	// On découpe le mot en fonction du nombre d'espace
	listeMot = mot.split(" ");
	// Pour tous les mots décomposés, on met la première lettre en majuscule
	for(int i = 0; i < listeMot.size(); i++) {
		mot = listeMot.at(i);
		if(mot.isEmpty())
			continue;
		mot.replace(0, 1, mot[0].toUpper());
		listeBis << mot;
	}
 
	mot = listeBis.join(" ");
}
[gui.ui]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>488</width>
    <height>356</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QTableView" name="tableView"/>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>488</width>
     <height>23</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuFichier">
    <property name="title">
     <string>Fichier</string>
    </property>
    <addaction name="actionNouveau"/>
    <addaction name="actionOuvrir"/>
    <addaction name="actionEnregistrer"/>
    <addaction name="actionEnregistrer_sous"/>
    <addaction name="separator"/>
    <addaction name="actionImprimer"/>
    <addaction name="separator"/>
    <addaction name="actionQuitter"/>
   </widget>
   <widget class="QMenu" name="menuAide">
    <property name="title">
     <string>Aide</string>
    </property>
    <addaction name="action_propos"/>
   </widget>
   <widget class="QMenu" name="menu_dition">
    <property name="title">
     <string>Édition</string>
    </property>
    <addaction name="actionAjouter_une_colonne"/>
    <addaction name="actionSupprimer_une_colonne"/>
    <addaction name="actionAjouter_un_eleve"/>
    <addaction name="actionSupprimer_un_eleve"/>
   </widget>
   <addaction name="menuFichier"/>
   <addaction name="menu_dition"/>
   <addaction name="menuAide"/>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
  <action name="actionOuvrir">
   <property name="text">
    <string>Ouvrir</string>
   </property>
  </action>
  <action name="actionEnregistrer">
   <property name="enabled">
    <bool>false</bool>
   </property>
   <property name="text">
    <string>Enregistrer</string>
   </property>
  </action>
  <action name="actionEnregistrer_sous">
   <property name="text">
    <string>Enregistrer sous</string>
   </property>
  </action>
  <action name="actionImprimer">
   <property name="text">
    <string>Imprimer</string>
   </property>
  </action>
  <action name="action_propos">
   <property name="text">
    <string>À propos</string>
   </property>
  </action>
  <action name="actionNouveau">
   <property name="text">
    <string>Nouveau</string>
   </property>
  </action>
  <action name="actionQuitter">
   <property name="text">
    <string>Quitter</string>
   </property>
  </action>
  <action name="actionAjouter_une_colonne">
   <property name="text">
    <string>Ajouter une colonne</string>
   </property>
  </action>
  <action name="actionSupprimer_une_colonne">
   <property name="text">
    <string>Supprimer une colonne</string>
   </property>
  </action>
  <action name="actionAjouter_un_eleve">
   <property name="text">
    <string>Ajouter un élève</string>
   </property>
  </action>
  <action name="actionSupprimer_un_eleve">
   <property name="text">
    <string>Supprimer un élève</string>
   </property>
  </action>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>actionQuitter</sender>
   <signal>activated()</signal>
   <receiver>MainWindow</receiver>
   <slot>close()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>-1</x>
     <y>-1</y>
    </hint>
    <hint type="destinationlabel">
     <x>243</x>
     <y>177</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>
Voilà