source: pyromaths/trunk/fuentes/src/pyromaths/interface.py @ 423

Last change on this file since 423 was 423, checked in by mabarracus, 4 years ago

add sources from pyromaths 15.10

File size: 33.6 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4# Pyromaths
5# Un programme en Python qui permet de créer des fiches d'exercices types de
6# mathématiques niveau collège ainsi que leur corrigé en LaTeX.
7# Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org)
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if notPopen, write to the Free Software
21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
23from PyQt4 import QtGui, QtCore
24import os, lxml, codecs, sys
25from outils import System
26from Values import CONFIGDIR, DATADIR, COPYRIGHTS, VERSION, ICONDIR
27from Values import lesfiches
28from operator import itemgetter
29
30class Ui_MainWindow(object):
31    def __init__(self, *args, **kwargs):
32        super(Ui_MainWindow, self).__init__(*args, **kwargs)
33        self.lesfiches = lesfiches()
34
35    def setupUi(self, MainWindow):
36        #============================================================
37        #        Initialisation
38        #============================================================
39        ## Lecture du fichier de configuration
40        self.configfile = os.path.join(CONFIGDIR, "pyromaths.xml")
41        self.liste_creation = []
42        self.config = self.lire_config('options')
43        ## Fenètre principale
44        if sys.platform != "darwin":  # Cas de Mac OS X.
45            MainWindow.setWindowIcon(QtGui.QIcon(ICONDIR))
46        MainWindow.setWindowTitle("Pyromaths")
47        MainWindow.setGeometry(0, 44, 900, 600)
48        font = QtGui.QFont()
49        font.setPointSize(10)
50        MainWindow.setFont(font)
51#         sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
52        ## Widget principal
53        self.centralwidget = QtGui.QWidget(MainWindow)
54        MainWindow.setCentralWidget(self.centralwidget)
55        ## Grille principale
56        self.gridLayout = QtGui.QGridLayout(self.centralwidget)
57
58        #============================================================
59        #        Boutons créer, quitter et annuler
60        #============================================================
61        ## Conteneur vertical
62        self.verticalLayout = QtGui.QVBoxLayout()
63        self.verticalLayout.setMargin(9)
64        self.gridLayout.addLayout(self.verticalLayout, 0, 1, 1, 1)
65        ## Bouton Créer
66        self.pushButton_ok = QtGui.QPushButton(self.centralwidget)
67        self.verticalLayout.addWidget(self.pushButton_ok)
68        self.pushButton_ok.setText(_(u"Créer"))
69        if sys.platform != "darwin":  # Cas de Mac OS X.
70            self.pushButton_ok.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));")
71        QtCore.QObject.connect(self.pushButton_ok, QtCore.SIGNAL("clicked()"), self.creer_les_exercices)
72        ## Bouton Quitter
73        self.pushButton_quit = QtGui.QPushButton(self.centralwidget)
74        self.verticalLayout.addWidget(self.pushButton_quit)
75        self.pushButton_quit.setText(_("Quitter"))
76        if sys.platform != "darwin":  # Cas de Mac OS X.
77            self.pushButton_quit.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));")
78        QtCore.QObject.connect(self.pushButton_quit, QtCore.SIGNAL("clicked()"), QtGui.qApp, QtCore.SLOT("quit()"))
79        ## Bouton Réinitialiser
80        self.pushButton_erase = QtGui.QPushButton(self.centralwidget)
81        self.verticalLayout.addWidget(self.pushButton_erase)
82        self.pushButton_erase.setText(_(u"Réinitialiser"))
83        if sys.platform != "darwin":  # Cas de Mac OS X.
84            self.pushButton_erase.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));")
85        QtCore.QObject.connect(self.pushButton_erase, QtCore.SIGNAL("clicked()"), self.effacer_choix_exercices)
86        ## Espace Vertical
87        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
88        self.verticalLayout.addItem(spacerItem)
89
90        #============================================================
91        #        Onglets de la zone centrale
92        #============================================================
93        ## Construction d'une zone d'onglet
94        self.tabWidget = QtGui.QTabWidget(self.centralwidget)
95        self.tabWidget.setAutoFillBackground(True)
96        self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
97
98        #============================================================
99        #        Remplissage des 4 niveaux
100        #============================================================
101        self.tabs = []
102        self.lesfiches.sort(key=itemgetter(0), reverse=True)
103        MESFICHES = [[self.lesfiches[i][0][2:], '', self.lesfiches[i][2]] for i in range(len(self.lesfiches))]
104
105        for level in MESFICHES:
106            self.tabs.append(Tab(self.tabWidget, level, self.setNbExos))
107
108        #============================================================
109        #        Onglet options
110        #============================================================
111        ## Creation d'une zone de scroll
112        self.tab_option_scroll = QtGui.QScrollArea(self.tabWidget)
113        self.tab_option_scroll.setFrameStyle(QtGui.QFrame.StyledPanel)
114        self.tab_option_scroll.setWidgetResizable(True)
115        self.tabWidget.addTab(self.tab_option_scroll, _("Options"))
116        ############## Onglet options
117
118        self.tab_options = QtGui.QWidget(self.tab_option_scroll)
119        if sys.platform != "darwin":  # Cas de Mac OS X.
120            self.tab_options.setStyleSheet("background-color: rgb(251, 245, 225);")
121        self.tab_option_scroll.setWidget(self.tab_options)
122
123
124
125
126        self.gridLayout_2 = QtGui.QGridLayout(self.tab_options)
127        self.horizontalLayout_options1 = QtGui.QHBoxLayout()
128
129        ############## Layout pour les noms d'options, en haut à gauche
130
131        self.verticalLayout_16 = QtGui.QVBoxLayout()
132
133        ############## Label nom du fichier
134
135        self.opt_nom_fichier = QtGui.QLabel(self.tab_options)
136        self.opt_nom_fichier.setText(_(u"Nom par défaut du fichier : "))
137        self.verticalLayout_16.addWidget(self.opt_nom_fichier)
138
139        ############## Label chemin par défaut pour l'enregistrement des fichiers
140
141        self.opt_chemin_fichier = QtGui.QLabel(self.tab_options)
142        self.opt_chemin_fichier.setText(_(u"Chemin par défaut pour enregistrer les fichiers : "))
143        self.verticalLayout_16.addWidget(self.opt_chemin_fichier)
144
145        ############## Label titre des fiches
146
147        self.opt_titre_fiche = QtGui.QLabel(self.tab_options)
148        self.opt_titre_fiche.setText(_("Titre de la fiche d'exercices : "))
149        self.verticalLayout_16.addWidget(self.opt_titre_fiche)
150        self.horizontalLayout_options1.addLayout(self.verticalLayout_16)
151
152        ############## Layout pour les noms d'options, en haut à droite
153
154        self.verticalLayout_17 = QtGui.QVBoxLayout()
155
156        ############## LineEdit nom du fichier
157
158        self.nom_fichier = QtGui.QLineEdit(self.tab_options)
159        self.nom_fichier.setText(self.config['nom_fichier'])
160        self.nom_fichier.setStyleSheet("background-color: rgb(255, 255, 255);")
161        self.verticalLayout_17.addWidget(self.nom_fichier)
162
163        ############## LineEdit chemin par défaut pour l'enregistrement des fichiers
164
165        self.horizontalLayout_chemin_fichier = QtGui.QHBoxLayout()
166        self.chemin_fichier = QtGui.QLineEdit(self.tab_options)
167        self.chemin_fichier.setText(self.config['chemin_fichier'])
168        self.chemin_fichier.setStyleSheet("background-color: rgb(255, 255, 255);")
169        self.horizontalLayout_chemin_fichier.addWidget(self.chemin_fichier)
170
171        ############## Bouton parcourir
172
173        self.pushButton_parcourir = QtGui.QPushButton(self.tab_options)
174        self.pushButton_parcourir.setText(_("Parcourir"))
175        if sys.platform != "darwin":  # Cas de Mac OS X.
176            self.pushButton_parcourir.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));")
177        self.horizontalLayout_chemin_fichier.addWidget(self.pushButton_parcourir)
178        self.verticalLayout_17.addLayout(self.horizontalLayout_chemin_fichier)
179        QtCore.QObject.connect(self.pushButton_parcourir, QtCore.SIGNAL("clicked()"), self.option_parcourir)
180
181        ############## LineEdit titre des fiches
182
183        self.titre_fiche = QtGui.QLineEdit(self.tab_options)
184        self.titre_fiche.setText(self.config['titre_fiche'])
185        self.titre_fiche.setStyleSheet("background-color: rgb(255, 255, 255);")
186        self.verticalLayout_17.addWidget(self.titre_fiche)
187        self.horizontalLayout_options1.addLayout(self.verticalLayout_17)
188        self.gridLayout_2.addLayout(self.horizontalLayout_options1, 0, 0, 1, 2)
189
190        ############## Ligne de séparation
191
192        self.line = QtGui.QFrame(self.tab_options)
193        self.line.setFrameShape(QtGui.QFrame.HLine)
194        self.line.setFrameShadow(QtGui.QFrame.Sunken)
195        self.gridLayout_2.addWidget(self.line, 1, 0, 1, 2)
196        self.horizontalLayout_3 = QtGui.QHBoxLayout()
197        self.verticalLayout_21 = QtGui.QVBoxLayout()
198
199        ############## CheckBox "corrigés ou non"
200
201        self.checkBox_corrige = QtGui.QCheckBox(self.tab_options)
202        self.checkBox_corrige.setText(_(u"Créer le corrigé"))
203        self.checkBox_corrige.setToolTip(_(u"Pyromaths doit-il créer la fiche de correction détaillée?"))
204        self.checkBox_corrige.setChecked(int(self.config['corrige']))
205        self.verticalLayout_21.addWidget(self.checkBox_corrige)
206        QtCore.QObject.connect(self.checkBox_corrige, QtCore.SIGNAL("stateChanged(int)"), self.option_corrige)
207
208        ############## CheckBox "pdf ou non"
209
210        self.checkBox_pdf = QtGui.QCheckBox(self.tab_options)
211        self.checkBox_pdf.setText(_(u"Créer le pdf"))
212        self.checkBox_pdf.setToolTip(_(u"Pyromaths doit-il créer les fiches au format pdf ?"))
213        self.checkBox_pdf.setChecked(int(self.config['pdf']))
214        self.verticalLayout_21.addWidget(self.checkBox_pdf)
215
216        ############## CheckBox "pdf ou non"
217
218        self.checkBox_unpdf = QtGui.QCheckBox(self.tab_options)
219        self.checkBox_unpdf.setText(_(u"Créer un seul pdf"))
220        self.checkBox_unpdf.setToolTip(_(u"Le corrigé et les exercices doivent-ils être dans le même document ?"))
221        self.checkBox_unpdf.setChecked(int(self.config['unpdf']))
222        self.verticalLayout_21.addWidget(self.checkBox_unpdf)
223
224        ############## Espace
225
226        self.horizontalLayout_3.addLayout(self.verticalLayout_21)
227        spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
228        self.horizontalLayout_3.addItem(spacerItem13)
229        self.verticalLayout_20 = QtGui.QVBoxLayout()
230        self.horizontalLayout_2 = QtGui.QHBoxLayout()
231        self.verticalLayout_18 = QtGui.QVBoxLayout()
232
233        ############## Label niveau
234
235        self.opt_niveau = QtGui.QLabel(self.tab_options)
236        self.opt_niveau.setText(_("Niveau :"))
237        self.verticalLayout_18.addWidget(self.opt_niveau)
238
239        ############## Label Modèle
240
241        self.label_modele = QtGui.QLabel(self.tab_options)
242        self.label_modele.setText(_(u"Modèle de mise en page :"))
243        # self.label_modele.setEnabled(False)
244        self.verticalLayout_18.addWidget(self.label_modele)
245        self.horizontalLayout_2.addLayout(self.verticalLayout_18)
246
247        ############## Layout pour les noms d'options, en bas à droite
248
249        self.verticalLayout_19 = QtGui.QVBoxLayout()
250
251        ############## ComboBox niveau
252
253        self.comboBox_niveau = QtGui.QComboBox(self.tab_options)
254        self.comboBox_niveau.setStyleSheet("background-color: rgb(255, 255, 255);")
255        self.comboBox_niveau.setEditable(True)  # l’utilisateur peut entrer son propre texte
256        self.comboBox_niveau.addItem(_("Classe de 6\\ieme"))
257        self.comboBox_niveau.addItem(_("Classe de 5\\ieme"))
258        self.comboBox_niveau.addItem(_("Classe de 4\\ieme"))
259        self.comboBox_niveau.addItem(_("Classe de 3\\ieme"))
260        self.comboBox_niveau.addItem(_("Classe de 2\\up{nde}"))
261        self.verticalLayout_19.addWidget(self.comboBox_niveau)
262
263        ############## ComboBox modèles
264
265        self.comboBox_modele = QtGui.QComboBox(self.tab_options)
266        self.comboBox_modele.setStyleSheet("background-color: rgb(255, 255, 255);")
267        modeles = os.listdir(os.path.join(DATADIR, 'templates'))
268        modeles_home = os.listdir(os.path.join(CONFIGDIR, 'templates'))
269
270        count = 0
271        for element in modeles:
272            if os.path.splitext(element)[1] == ".tex":
273                self.comboBox_modele.addItem(str(element[:len(element) - 4]))
274                if element == self.config['modele']:
275                    self.comboBox_modele.setCurrentIndex(count)
276                count += 1
277        for element in modeles_home:
278            if os.path.splitext(element)[1] == ".tex":
279                self.comboBox_modele.addItem(QtCore.QString())
280                self.comboBox_modele.setItemText(count, str(element[:len(element) - 4]))
281                if element == self.config['modele']:
282                    self.comboBox_modele.setCurrentIndex(count)
283                count += 1
284
285        self.verticalLayout_19.addWidget(self.comboBox_modele)
286        self.horizontalLayout_2.addLayout(self.verticalLayout_19)
287        self.verticalLayout_20.addLayout(self.horizontalLayout_2)
288        self.horizontalLayout_3.addLayout(self.verticalLayout_20)
289        self.gridLayout_2.addLayout(self.horizontalLayout_3, 2, 0, 1, 2)
290
291        ############## Bouton enregistrer
292
293        self.pushButton_enr_opt = QtGui.QPushButton(self.tab_options)
294        self.pushButton_enr_opt.setText(_(u"Enregistrer dans les préférences"))
295        if sys.platform != "darwin":  # Cas de Mac OS X.
296            self.pushButton_enr_opt.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(243, 165, 30, 255), stop:1 rgba(255, 247, 177, 255));")
297        QtCore.QObject.connect(self.pushButton_enr_opt, QtCore.SIGNAL("clicked()"), self.enregistrer_config)
298
299        self.gridLayout_2.addWidget(self.pushButton_enr_opt, 4, 1, 1, 1)
300        spacerItem14 = QtGui.QSpacerItem(20, 177, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
301        self.gridLayout_2.addItem(spacerItem14, 3, 1, 1, 1)
302        spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
303        self.gridLayout_2.addItem(spacerItem15, 4, 0, 1, 1)
304
305        #============================================================
306        #        Barre de menus et de status
307        #============================================================
308        ## Construction de la barre
309        self.menubar = QtGui.QMenuBar(MainWindow)
310        self.menubar.setGeometry(QtCore.QRect(0, 0, 700, 22))
311        MainWindow.setMenuBar(self.menubar)
312        ## Menu Fichier
313        if sys.platform != "darwin":  # Cas de Mac OS X.
314                self.menuFichier = QtGui.QMenu(self.menubar)
315                self.menuFichier.setTitle(_("Fichier"))
316        ## Action Quitter
317        self.actionQuitter = QtGui.QAction(MainWindow)
318        self.actionQuitter.setText(_("Quitter"))
319        self.actionQuitter.setShortcut('Ctrl+Q')
320        QtCore.QObject.connect(self.actionQuitter, QtCore.SIGNAL("triggered()"), QtGui.qApp, QtCore.SLOT("quit()"))
321        ## Menu Aide
322        self.menu_propos = QtGui.QMenu(self.menubar)
323        self.menu_propos.setTitle(_("Aide"))
324        ## Action Accéder au site
325        self.actionAcceder_au_site = QtGui.QAction(MainWindow)
326        self.actionAcceder_au_site.setText(_(u"Accéder au site"))
327        QtCore.QObject.connect(self.actionAcceder_au_site, QtCore.SIGNAL("triggered()"), self.site)
328        ## Action À propos
329        self.action_a_propos = QtGui.QAction(MainWindow)
330        self.action_a_propos.setText(_(u"À propos"))
331        self.action_a_propos.setMenuRole(QtGui.QAction.AboutRole)
332        QtCore.QObject.connect(self.action_a_propos, QtCore.SIGNAL("triggered()"), self.about)
333        ## Construction du menu
334        if sys.platform != "darwin":
335            self.menuFichier.addSeparator()
336            self.menuFichier.addAction(self.actionQuitter)
337        self.menu_propos.addAction(self.actionAcceder_au_site)
338        self.menu_propos.addSeparator()
339        self.menu_propos.addAction(self.action_a_propos)
340        if sys.platform != "darwin":
341            self.menubar.addAction(self.menuFichier.menuAction())
342        self.menubar.addAction(self.menu_propos.menuAction())
343
344        #============================================================
345        #        Barre d'état
346        #============================================================
347        ## Construction de la barre d'état
348        self.statusbar = QtGui.QStatusBar(MainWindow)
349        MainWindow.setStatusBar(self.statusbar)
350        ## Message d'aide
351        self.statusbar_label= QtGui.QLabel(self.statusbar)
352        self.statusbar_label.setText(_(u"Pour avoir un aperçu d'un exercice, positionner le curseur de la souris sur le point d'interrogation."))
353        self.statusbar.addWidget(self.statusbar_label,1)
354
355        #QtCore.QMetaObject.connectSlotsByName(MainWindow) #inutile ???
356
357    #============================================================
358    #        Début des fonctions
359    #============================================================
360
361    # ## Gestion des erreurs
362    def erreur_critique(self, message):
363        """Dialogue si pyromaths.xml est défectueux."""
364        reply = QtGui.QMessageBox.critical(self, "Erreur critique", message)
365        if reply:
366            sys.exit(1)
367
368
369    def about(self):
370        """Crée la boîte de dialogue "À propos de..." """
371        text = _(u"""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
372<html>
373  <head>
374    <meta name="qrichtext" content="1" />
375    <style type="text/css">
376      p, li { white-space: pre-wrap; align:"justify"; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:5px; -qt-block-indent:0; text-indent:0px; }
377    </style>
378  </head>
379  <body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;" bgcolor="#f9efbe">
380    <p align="center">
381    <img src="%s" />
382    <br /><br />
383    <span style="font-weight:600;">Version %s</span>
384    </p>
385    <p>
386    <span style=" font-weight:600;">Pyromaths</span> est un programme qui permet de créer des  fiches d'exercices types de mathématiques niveau collège avec leur corrigé.
387    </p>
388    <p>
389    Les fiches sont produites au format LaTeX. Pyromaths lance ensuite les commandes nécessaires à la production de fichiers pdf (latex - dvips - ps2pdf) et les ouvre.
390    </p>
391    <p align="center">
392    <span style=" text-decoration: underline;">Remerciements à&nbsp;:</span>
393    </p>
394    <p>
395    <ul style="-qt-list-indent:1;">
396      <li>
397      <span style=" font-weight:600;">David Robert</span> pour l'idée de départ&nbsp;;
398      </li>
399      <li>
400      <span style=" font-weight:600;">Yves Gesnel</span> pour le portage de Pyromaths sur Mac OS X et la conception d'exercices&nbsp;;
401      </li>
402      <li>
403      <span style=" font-weight:600;">Arnaud Kientz</span> pour ses graphismes, son implication dans le code de Pyromaths et son amitié&nbsp;;
404      </li>
405      <li>
406      <span style=" font-weight:600;">Guillaume Barthélémy</span> pour ses exercices&nbsp;;
407      </li>
408      <li>
409      <span style=" font-weight:600;">Nicolas Bissonnier</span> pour son arrivée dans l'équipe de développement&nbsp;;
410      </li>
411      <li>
412      <span style=" font-weight:600;">Didier Roche</span> pour l'intégration de Pyromaths dans les dépôts Ubuntu&nbsp;;
413      </li>
414      <li>
415      <span style=" font-weight:600;">Olivier Cornu</span> pour son travail sur l'API exercice et sur la diffusion de Pyromaths via Makefile et Setup.py&nbsp;;
416      </li>
417      <li>
418      <span style=" font-weight:600;">Jacqueline Gouguenheim-Desloy</span> a porté Pyromaths sur Mac OS X à ses débuts. Son soutien et son amitié nous ont été précieux. Sa disparition est une perte douloureuse pour la communauté du logiciel libre.
419      </li>
420    </ul>
421    </p>
422    <p align="center">
423    %s
424    </p>
425  </body>
426</html>""")
427        if sys.platform == "darwin":  # Cas de Mac OS X.
428            banniere = os.path.join(DATADIR, 'images', 'pyromaths.png')
429        else:
430            banniere = os.path.join(DATADIR, 'images', 'pyromaths-banniere.png')
431        QtGui.QMessageBox.about(self.centralwidget, _(u'À propos de Pyromaths'), text % (banniere, VERSION, COPYRIGHTS))
432
433    def creer_les_exercices(self):
434        """Vérifie si la liste d'exercices n'est pas vide puis sélectionne les noms des fichiers exercices et
435        corrigés"""
436        self.valide_options()
437        if self.liste_creation == [] :
438            QtGui.QMessageBox.warning(None, _('Attention !'),
439                    _(u"Veuillez sélectionner des exercices..."),
440                    QtGui.QMessageBox.Ok)
441        else:
442            parametres = {
443                'creer_pdf': self.checkBox_pdf.isChecked(),
444                'creer_unpdf': self.checkBox_unpdf.isChecked() and self.checkBox_unpdf.isEnabled(),
445                'titre': unicode(self.titre_fiche.text()),
446                'corrige': self.checkBox_corrige.isChecked(),
447                'niveau': unicode(self.comboBox_niveau.currentText()),
448                'nom_fichier': unicode(self.nom_fichier.text()),
449                'chemin_fichier': unicode(self.chemin_fichier.text()),
450                'modele': unicode(self.comboBox_modele.currentText() + '.tex'),
451                'datadir': DATADIR,
452                'configdir': CONFIGDIR
453                         }
454            #============================================================
455            #        Choix de l'ordre des exercices
456            #============================================================
457            liste = []
458            for i in range(len(self.liste_creation)):
459                niveau = self.liste_creation[i][0]
460                exo = self.liste_creation[i][1]
461                liste.append(self.lesfiches[niveau][2][exo])
462            self.List = QtGui.QListWidget()
463            for i in range(len(liste)):
464                item = QtGui.QListWidgetItem(liste[i].description)
465                item.setFlags(QtCore.Qt.ItemIsEnabled |
466                              QtCore.Qt.ItemIsSelectable |
467                              QtCore.Qt.ItemIsDragEnabled)
468                item.exercice = liste[i]
469                self.List.addItem(item)
470            bmono = True
471            for i in range(len(liste)):
472                if liste[0] != liste[i]: bmono = False
473            if bmono:
474                # S'il ny a qu'un seul type d'exercices, pas la peine de choisir
475                # l'ordre
476                valide(self.List, self.lesfiches, parametres)
477            else:
478                form = ChoixOrdreExos(self.List, self.lesfiches, parametres, self.centralwidget)
479                form.exec_()
480
481    def effacer_choix_exercices(self):
482        """Remet toutes les SpinBox à zéro et vide la liste d'exercices sélectionnés"""
483        self.liste_creation = []
484        for tab in self.tabs:
485            tab.reset()
486
487    def enregistrer_config(self):
488        """Fonction qui se charge d'enregistrer les options de l'interface dans le fichier de configuration
489        après avoir complété le dictionnaire."""
490        tree = lxml.etree.parse(self.configfile)
491        root = tree.getroot()
492        options = root.find('options')
493        options .find('nom_fichier').text = unicode(self.nom_fichier.text())
494        options .find('chemin_fichier').text = unicode(self.chemin_fichier.text())
495        options .find('titre_fiche').text = unicode(self.titre_fiche.text())
496        options .find('corrige').text = str(self.checkBox_corrige.isChecked())
497        options .find('pdf').text = str(self.checkBox_pdf.isChecked())
498        options .find('unpdf').text = str(self.checkBox_unpdf.isChecked())
499        options .find('modele').text = unicode(self.comboBox_modele.currentText() + '.tex')
500
501        f = codecs.open(self.configfile, encoding='utf-8', mode='w')
502        f.write(lxml.etree.tostring(root, pretty_print=True, encoding="UTF-8",
503                               xml_declaration=True).decode('utf-8', 'strict'))
504        f.close()
505
506    def lire_config(self, section):
507        """Lis le fichier de configuration pyromaths.conf, enregistre les données dans un dictionnaire config"""
508        config = {}
509        tree = lxml.etree.parse(self.configfile)
510        root = tree.getroot()
511        options = root.find(section)
512        for child in options:
513            if child.text == 'True': text = '1'
514            elif child.text == 'False': text = '0'
515            else : text = child.text
516            config[child.tag] = text
517        return config
518
519    def option_parcourir(self):
520        d0 = QtGui.QFileDialog().getExistingDirectory (None, _(u"Dossier où créer les fiches"),
521                                                       self.config['chemin_fichier'], QtGui.QFileDialog.ShowDirsOnly)
522        if d0:
523            self.chemin_fichier.setText(d0)
524
525    def option_corrige(self):
526        if not self.checkBox_corrige.isChecked():
527            self.checkBox_unpdf.setChecked(False)
528            self.checkBox_unpdf.setEnabled(False)
529        else:
530            self.checkBox_unpdf.setEnabled(True)
531
532    def setNbExos(self):
533        """Modifie le nombre d'exercices dans la variable liste_creation lorsqu'on  modifie une spinBox
534        et adapte le niveau affiché dans l'en-tête de la fiche en fonction du plus haut niveau d'exercice"""
535        niveau = 0
536        self.liste_creation = []
537        for pkg_no in range(len(self.tabs)):
538            for box in range(len(self.lesfiches[pkg_no][2])):
539                qte = self.tabs[pkg_no].spinBox[box].value()
540                for dummy in range(qte):
541                    self.liste_creation.append((pkg_no, box))
542                    if pkg_no > niveau:
543                        niveau = pkg_no
544        self.comboBox_niveau.setCurrentIndex(niveau)
545
546    def site(self):
547        """Ouvre le navigatuer internet par défaut sur la page d'accueil du site http://www.pyromaths.org"""
548        import webbrowser
549        webbrowser.open('http://www.pyromaths.org')
550
551
552    def valide_options(self):
553        """Synchronise les options éventuellement saisies par l'utilisag
554QCoreApplication::exec: The event loop is already runningteur avec le dictionnaire de config"""
555        self.config['chemin_fichier'] = self.chemin_fichier.text()
556        self.config['nom_fichier'] = self.nom_fichier.text()
557        self.config['titre_fiche'] = self.titre_fiche.text()
558        self.config['corrige'] = self.checkBox_corrige.isChecked()
559        self.config['pdf'] = self.checkBox_pdf.isChecked()
560        self.config['unpdf'] = self.checkBox_unpdf.isChecked()and self.checkBox_unpdf.isEnabled()
561
562#================================================================
563#        Classe ChoixOrdreExos
564#================================================================
565
566class ChoixOrdreExos(QtGui.QDialog):
567    """À appeler de la façon suivante :
568    form = ChoixOrdreExos(liste, LesFiches, parametres)
569    Permet de choisir l'ordre dans lequel les exercices vont apparaître
570    parametres = {'fiche_exo':
571                  'fiche_cor':
572                  'liste_exos':
573                  'creer_pdf':
574                  'titre':
575                  'corrige':
576                  'niveau':
577                  'nom_fichier':
578                  'chemin_fichier':
579                 }"""
580
581    def __init__(self, liste, LesFiches, parametres, parent=None):
582        self.lesfiches = LesFiches
583        self.parametres = parametres
584        self.List = liste
585        QtGui.QDialog.__init__(self, parent)
586        self.setWindowTitle(_("Choisissez l'ordre des exercices"))
587        layout = QtGui.QHBoxLayout()
588
589        buttonBox = QtGui.QDialogButtonBox()
590        buttonBox.setOrientation(QtCore.Qt.Vertical)
591        buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok)
592
593        self.List.setAlternatingRowColors(True)
594        self.List.setDragEnabled(True)
595        self.List.setAcceptDrops(True)
596        self.List.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
597        self.List.setDropIndicatorShown(True)
598
599        layout.addWidget(self.List)
600        layout.addWidget(buttonBox)
601        self.setLayout(layout)
602
603        QtCore.QObject.connect(buttonBox, QtCore.SIGNAL("accepted()"), self.accept)
604        QtCore.QObject.connect(buttonBox, QtCore.SIGNAL("rejected()"), self.close)
605
606    def accept(self):
607        """Écrit une liste contenant la liste des exercices dans l'ordre choisit par l'utilisateur et demande à
608        celui-ci les noms de fichiers pour les exercices et les corrigés"""
609        valide(self.List, self.lesfiches, self.parametres)
610        self.close()
611
612def valide(liste, LesFiches, parametres):
613    """ Permet de choisir les noms et emplacements des fichiers tex, les écrits
614    et lance la compilation LaTex"""
615    corrige = parametres['corrige']
616    lesexos = []
617    for i in range(liste.count()):
618        lesexos.append(liste.item(i).exercice())
619
620    #============================================================
621    #        Choix des noms des fichiers exercices et corrigés
622    #============================================================
623    saveas = QtGui.QFileDialog()
624    filename = System.supprime_extension(parametres['nom_fichier'],
625                                         '.tex')
626    f0 = unicode(saveas.getSaveFileName(None, "Enregistrer sous...",
627                os.path.join(parametres['chemin_fichier'],
628                             u'%s.tex' % filename), "Documents Tex (*.tex)"))
629    if f0:
630        System.ajoute_extension(f0, '.tex')
631        if corrige and not parametres['creer_unpdf']:
632            f1 = unicode(saveas.getSaveFileName(None, "Enregistrer sous...",
633                os.path.join(os.path.dirname(f0),
634                _(u"%s-corrige.tex") % os.path.splitext(os.path.basename(f0))[0]),
635                _("Documents Tex (*.tex)")))
636        else:
637            f1 = os.path.join(os.path.dirname(f0), _(u"%s-corrige.tex") %
638                              os.path.splitext(os.path.basename(f0))[0])
639        if f1:
640            if corrige:
641                System.ajoute_extension(f1, '.tex')
642            parametres ['fiche_exo'] = f0
643            parametres ['fiche_cor'] = f1
644            parametres ['liste_exos'] = lesexos
645            parametres ['les_fiches'] = LesFiches
646            System.creation(parametres)
647
648#================================================================
649#        Classe Tab
650#================================================================
651
652class Tab(QtGui.QWidget):
653    """Gère les onglets permettant de sélectionner des exercices"""
654
655    def __init__(self, parent, level, onchange):
656        QtGui.QWidget.__init__(self)  # Initialise la super-classe
657        self.titre = level[0]
658        self.exos = level[2]
659        self.scroll = QtGui.QScrollArea(self)
660        self.scroll.setFrameStyle(QtGui.QFrame.StyledPanel)
661        self.scroll.setWidgetResizable(True)
662        self.widget = QtGui.QWidget(self.scroll)
663        self.scroll.setWidget(self.widget)
664        if sys.platform != "darwin":  # Cas de Mac OS X.
665            self.widget.setStyleSheet("background-color: rgb(251, 245, 225);")
666        self.layout = QtGui.QGridLayout(self.widget)
667        self.spinBox = []
668        # Crée les widgets des exercices
669        nb_exos = len(self.exos)
670        spacer = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
671        for i in range(nb_exos):
672            self.add_exercise(i, onchange)
673            self.layout.addItem(spacer, (nb_exos + 1) / 2, 0, 1, 1)
674            self.layout.addItem(spacer, (nb_exos + 1) / 2, 1, 1, 1)
675        # Ajoute ce tab au widget parent
676        parent.addTab(self.scroll, self.titre)
677
678
679
680    def add_exercise(self, i, onchange):
681        """Ajoute l'exercice n°i à cet onglet"""
682        layout = QtGui.QHBoxLayout()
683        # SpinBox
684        spinBox = QtGui.QSpinBox(self.widget)
685        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
686        sizePolicy.setHorizontalStretch(40)
687        sizePolicy.setVerticalStretch(30)
688        sizePolicy.setHeightForWidth(spinBox.sizePolicy().hasHeightForWidth())
689        spinBox.setSizePolicy(sizePolicy)
690        spinBox.setToolTip(_(u"Choisissez le nombre d\'exercices de ce type à créer."))
691        spinBox.setStyleSheet("background-color: rgb(255, 255, 255);")
692        QtCore.QObject.connect(spinBox, QtCore.SIGNAL("valueChanged(int)"), onchange)
693        self.spinBox.append(spinBox)
694        layout.addWidget(spinBox)
695        # Image
696        img = QtGui.QLabel(self.widget)
697        img.setText(r'<img src="%s"/>' % os.path.join(DATADIR, 'images', 'whatsthis.png'))
698        img.setToolTip(r'<img src="%s"/>' % self.exos[i].thumb())
699        layout.addWidget(img)
700        # Label
701        label = QtGui.QLabel(self.widget)
702        label.setText(self.exos[i].description)
703        layout.addWidget(label)
704        # Espacements
705        spacer = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
706        layout.addItem(spacer)
707        layout.addItem(spacer)
708        # Ajoute cet exercice à l'onglet
709        self.layout.addLayout(layout, i / 2, i % 2, 1, 1)
710
711    def reset(self):
712        """Remet les compteurs à zéro"""
713        for i in range(len(self.exos)):
714            self.spinBox[i].setValue(0)
Note: See TracBrowser for help on using the repository browser.