excel2moodle 0.3.4__py3-none-any.whl → 0.3.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- """Script for verifying the equations written into the ``result`` field of NFM-type Question
1
+ """Script for verifying the equations written into the ``result`` field of NFM-type Question.
2
2
 
3
3
  This script does two things.
4
4
 
@@ -40,7 +40,7 @@ from excel2moodle.core import numericMultiQ as nmq
40
40
 
41
41
 
42
42
  def checkResult(checkerValue: float, calculation: float, tolerance=0.01) -> bool:
43
- """Checks if the two Arguments are within the tolerance the same value
43
+ """Checks if the two Arguments are within the tolerance the same value.
44
44
 
45
45
  :param checkerValue: the value the calculation is compared against
46
46
  :type checkerValue: fleat
@@ -54,19 +54,15 @@ def checkResult(checkerValue: float, calculation: float, tolerance=0.01) -> bool
54
54
  False if checkerValue != calculation
55
55
  :rtype: bool
56
56
  """
57
-
58
57
  upper = abs(checkerValue + checkerValue * tolerance)
59
58
  lower = abs(checkerValue - checkerValue * tolerance)
60
- if abs(calculation) > lower and abs(calculation) < upper:
61
- return True
62
- else:
63
- return False
59
+ return bool(abs(calculation) > lower and abs(calculation) < upper)
64
60
 
65
61
 
66
62
  def equationChecker(
67
63
  categoryName: str, qNumber: int, spreadsheetFile
68
64
  ) -> tuple[list[str], list[float], float]:
69
- """This Function calculates all Results an invokes the checkResult function
65
+ """This Function calculates all Results an invokes the checkResult function.
70
66
 
71
67
  Parameters
72
68
  ----------
@@ -86,8 +82,8 @@ def equationChecker(
86
82
  The list with the calculated results
87
83
  checkerValue : float
88
84
  The value taken from the ``firstResult`` field
89
- """
90
85
 
86
+ """
91
87
  spreadsheetFile.resolve()
92
88
  df = pd.read_excel(spreadsheetFile, sheet_name=categoryName, index_col=0)
93
89
  eq = df.loc["result"][qNumber]
@@ -95,7 +91,6 @@ def equationChecker(
95
91
  try:
96
92
  res = float(df.loc["firstResult"][qNumber])
97
93
  except Exception:
98
- print(f"Es ist kein 'firstResult' gegeben, kann nichts überprüfen")
99
94
  res = 0
100
95
  bps, calcs = nmq.parseNumericMultiQuestion(df, bps, eq, qNumber)
101
96
  return bps, calcs, res
@@ -106,11 +101,11 @@ def main(
106
101
  catN=None,
107
102
  qNumber=None,
108
103
  ) -> None:
109
- """Takes the Spreadsheet, and asks for a category and a question number"""
110
- if catN == None:
104
+ """Takes the Spreadsheet, and asks for a category and a question number."""
105
+ if catN is None:
111
106
  catN = input("Geben Sie die Kategorie an: KAT_")
112
107
  categoryName = f"KAT_{catN}"
113
- if qNumber == None:
108
+ if qNumber is None:
114
109
  qNumber = int(input("Geben Sie die Fragennummer an: "))
115
110
  bullets, results, firstResult = equationChecker(
116
111
  categoryName, qNumber, spreadsheetFile=spreadsheetFile
@@ -120,23 +115,14 @@ def main(
120
115
  for i, calculation in enumerate(results):
121
116
  if i == 0 and firstResult != 0:
122
117
  check = checkResult(firstResult, calculation)
123
- print(
124
- f"Ergebnis {
125
- i+1}: \t{calculation}\n\tMit den Werten: \n{bullets[i]}\n"
126
- )
127
-
128
- if check == True:
129
- print(
130
- f"Das erste berechnete Ergebnis stimmt mit dem Wert in 'firstResult' überein\n"
131
- )
118
+
119
+ if check:
120
+ pass
132
121
  else:
133
- print(
134
- f"WARNUNG: Das erste berechnete Ergebnis weicht von dem Wert {
135
- firstResult=} ab.\n"
136
- )
122
+ pass
137
123
 
138
124
 
139
125
  if __name__ == "__main__":
140
- spreadsheet = input(f"Geben Sie den Pfad zu dem spreadsheet an:")
126
+ spreadsheet = input("Geben Sie den Pfad zu dem spreadsheet an:")
141
127
  while True:
142
128
  main(Path(spreadsheet))
excel2moodle/logger.py ADDED
@@ -0,0 +1,102 @@
1
+ """Logging Setup for Excel2moodle.
2
+
3
+ Mainly this sets up the general configuration.
4
+ This includes emitting the signals for the main Window, to fast forward all logs.
5
+ """
6
+
7
+ import logging
8
+
9
+ from PySide6.QtCore import QObject, Signal
10
+
11
+ from excel2moodle.ui.settings import Settings, SettingsKey
12
+
13
+ settings = Settings()
14
+
15
+ loggerConfig = {
16
+ "version": 1,
17
+ "disable_existing_loggers": False,
18
+ "formatters": {
19
+ "standard": {
20
+ "format": "[{levelname:^8s}] {module:.^14s}: {message}",
21
+ "style": "{",
22
+ },
23
+ "file": {
24
+ "format": "%(asctime)s [%(levelname)-5s] %(name)12s: %(message)s",
25
+ },
26
+ },
27
+ "handlers": {
28
+ "default": {
29
+ "level": "DEBUG",
30
+ "formatter": "standard",
31
+ "class": "logging.StreamHandler",
32
+ "stream": "ext://sys.stdout", # Default is stderr
33
+ },
34
+ "file": {
35
+ "level": "DEBUG",
36
+ "formatter": "file",
37
+ "class": "logging.FileHandler",
38
+ # "class": "logging.handlers.TimedRotatingFileHandler",
39
+ "filename": settings.get(SettingsKey.LOGFILE),
40
+ # "when": "M",
41
+ # "interval": 1,
42
+ # "backupCount": "3",
43
+ "delay": "true",
44
+ },
45
+ },
46
+ "loggers": {
47
+ "": { # root logger
48
+ "handlers": ["default", "file"],
49
+ "level": "DEBUG",
50
+ "propagate": True,
51
+ },
52
+ "excel2moodle.questionParser": {
53
+ "handlers": ["default"],
54
+ "level": "DEBUG",
55
+ "propagate": True,
56
+ },
57
+ "__main__": { # if __name__ == '__main__'
58
+ "handlers": ["default"],
59
+ "level": "DEBUG",
60
+ "propagate": True,
61
+ },
62
+ },
63
+ }
64
+
65
+
66
+ class QSignaler(QObject):
67
+ signal = Signal(str)
68
+
69
+
70
+ class LogWindowHandler(logging.Handler):
71
+ def __init__(self, *args, **kwargs) -> None:
72
+ super().__init__(*args, **kwargs)
73
+ self.emitter = QSignaler()
74
+ # Define a formatter with log level and module
75
+ log_format = "[%(levelname)s] %(module)s: %(message)s"
76
+ self.formatter = logging.Formatter(log_format)
77
+ self.setFormatter(self.formatter)
78
+ loglevel = settings.get(SettingsKey.LOGLEVEL)
79
+ self.setLevel(loglevel)
80
+ self.logLevelColors = {
81
+ "DEBUG": "gray",
82
+ "INFO": "green",
83
+ "WARNING": "orange",
84
+ "ERROR": "red",
85
+ "CRITICAL": "pink",
86
+ }
87
+
88
+ def emit(self, record: logging.LogRecord) -> None:
89
+ """Emit the signal, with a new logging message."""
90
+ log_message = self.format(record)
91
+ color = self.logLevelColors.get(record.levelname, "black")
92
+ prettyMessage = f'<span style="color:{color};">{log_message}</span>'
93
+ print("emitting new log signal") # noqa:T201
94
+ self.emitter.signal.emit(prettyMessage)
95
+
96
+
97
+ class LogAdapterQuestionID(logging.LoggerAdapter):
98
+ """Prepend the Question ID to the logging messages."""
99
+
100
+ def process(self, msg, kwargs):
101
+ """Append the Question ID to the log Message."""
102
+ return "[{}]: {}".format(self.extra["qID"], msg), kwargs
excel2moodle/ui/appUi.py CHANGED
@@ -1,20 +1,22 @@
1
- """This Module holds the extended class mainWindow() and any other main Windows
1
+ """AppUi holds the extended class mainWindow() and any other main Windows.
2
2
 
3
- It needs to be seperated from ``windowMain.py`` because that file will be changed by tho ``pyside6-uic`` command,
4
- which generates the python code from the ``.ui`` file
3
+ It needs to be seperated from ``windowMain.py`` because that file will be changed by the
4
+ ``pyside6-uic`` command, which generates the python code from the ``.ui`` file
5
5
  """
6
6
 
7
- import logging as logging
7
+ import logging
8
8
  from pathlib import Path
9
9
 
10
10
  from PySide6 import QtCore, QtWidgets
11
11
  from PySide6.QtCore import Qt
12
12
 
13
- from excel2moodle import e2mMetadata, qSignalLogger
13
+ from excel2moodle import qSignalLogger
14
+
15
+ # from excel2moodle.logger import LogWindowHandler
14
16
  from excel2moodle.core.dataStructure import QuestionDB
15
17
  from excel2moodle.extra import equationVerification as eqVerif
16
- from excel2moodle.ui import dialogs, windowEquationChecker
17
- from excel2moodle.ui.settings import Settings
18
+ from excel2moodle.ui import dialogs
19
+ from excel2moodle.ui.settings import Settings, SettingsKey
18
20
  from excel2moodle.ui.treewidget import CategoryItem, QuestionItem
19
21
  from excel2moodle.ui.windowMain import Ui_MoodleTestGenerator
20
22
 
@@ -36,18 +38,18 @@ class MainWindow(QtWidgets.QMainWindow):
36
38
 
37
39
  self.ui.treeWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
38
40
  self.ui.treeWidget.header().setSectionResizeMode(
39
- QtWidgets.QHeaderView.ResizeToContents
41
+ QtWidgets.QHeaderView.ResizeToContents,
40
42
  )
41
43
  self.ui.checkBoxIncludeCategories.setChecked(
42
- self.settings.value("testGen/includeCats", type=bool)
44
+ self.settings.get(SettingsKey.INCLUDEINCATS),
43
45
  )
44
46
 
45
47
  self.ui.retranslateUi(self)
46
- logger.info(f"Settings are stored under: {self.settings.fileName()}")
48
+ logger.info("Settings are stored under: %s", self.settings.fileName())
47
49
  self.ui.pointCounter.setReadOnly(True)
48
50
  self.ui.questionCounter.setReadOnly(True)
49
51
  self.setStatus(
50
- "Wählen Sie bitte eine Excel Tabelle und einen Export Ordner für die Fragen aus"
52
+ "Wählen Sie bitte eine Excel Tabelle und einen Export Ordner für die Fragen aus",
51
53
  )
52
54
  try:
53
55
  self.resize(self.settings.value("windowSize"))
@@ -59,78 +61,55 @@ class MainWindow(QtWidgets.QMainWindow):
59
61
  def connectEvents(self) -> None:
60
62
  self.ui.treeWidget.itemClicked.connect(self.onSelectionChanged)
61
63
  self.ui.checkBoxQuestionListSelectAll.checkStateChanged.connect(
62
- self.toggleQuestionSelectionState
64
+ self.toggleQuestionSelectionState,
63
65
  )
64
66
  qSignalLogger.emitter.signal.connect(self.updateLog)
65
- self.ui.actionEquationChecker.triggered.connect(self.onButOpenEqChecker)
67
+ self.ui.actionEquationChecker.triggered.connect(self.openEqCheckerDlg)
66
68
  self.ui.checkBoxIncludeCategories.checkStateChanged.connect(
67
- self.setIncludeCategoriesSetting
69
+ self.setIncludeCategoriesSetting,
68
70
  )
69
- # self.ui.buttonRefresh.clicked.connect(self.refreshList)
70
71
  self.ui.actionParseAll.triggered.connect(self.onParseAll)
71
- self.testDB.dataChanged.signal.connect(self.onParseAll)
72
+ self.testDB.dataChanged.signal.connect(self.refreshList)
72
73
  self.ui.buttonSpreadSheet.clicked.connect(self.onButSpreadsheet)
73
74
  self.ui.buttonTestGen.clicked.connect(self.onButGenTest)
74
- self.ui.actionPreviewQ.triggered.connect(self.previewQ)
75
- self.ui.actionAbout.triggered.connect(self.onAbout)
75
+ self.ui.actionPreviewQ.triggered.connect(self.openPreviewQuestionDlg)
76
+ self.ui.actionAbout.triggered.connect(self.openAboutDlg)
76
77
  self.settings.shPathChanged.connect(self.onSheetPathChanged)
78
+ self.ui.spinBoxDefaultQVariant.valueChanged.connect(self.setQVariantDefault)
79
+
80
+ @QtCore.Slot()
81
+ def setQVariantDefault(self, value: int) -> None:
82
+ self.settings.set(SettingsKey.QUESTIONVARIANT, value)
77
83
 
78
84
  @QtCore.Slot(Path)
79
85
  def onSheetPathChanged(self, sheet: Path) -> None:
80
86
  logger.debug("Slot, new Spreadsheet triggered")
81
87
  self.spreadSheetPath = sheet
82
88
  self.mainPath = sheet.parent
89
+ svgFolder = self.mainPath / self.settings.get(SettingsKey.PICTURESUBFOLDER)
90
+ svgFolder.resolve()
91
+ self.settings.set(SettingsKey.PICTUREFOLDER, svgFolder)
83
92
  self.ui.buttonSpreadSheet.setText(str(sheet.name))
93
+ self.testDB.readSpreadsheetData(self.spreadSheetPath)
94
+ self.testDB.parseAll()
95
+ self.refreshList()
84
96
 
85
97
  def updateLog(self, log) -> None:
86
98
  self.ui.loggerWindow.append(log)
87
99
 
88
- def setIncludeCategoriesSetting(self):
100
+ def setIncludeCategoriesSetting(self) -> None:
89
101
  if self.ui.checkBoxIncludeCategories.isChecked():
90
- self.settings.testgenSet("includeCats", True)
91
- logger.debug("set includeCats to True")
102
+ self.settings.set(SettingsKey.INCLUDEINCATS, True)
92
103
  else:
93
- self.settings.testgenSet("includeCats", False)
94
- logger.debug("set includeCats to False")
104
+ self.settings.set(SettingsKey.INCLUDEINCATS, False)
95
105
 
96
- @QtCore.Slot()
97
- def onAbout(self):
98
- aboutMessage: str = f"""
99
- <h1> About {e2mMetadata['name']}</h1><br>
100
- <p style="text-align:center">
101
-
102
- <b><a href="{e2mMetadata['homepage']}">{e2mMetadata['name']}</a> - {e2mMetadata['description']}</b>
103
- </p>
104
- <p style="text-align:center">
105
- The documentation can be found under <b>
106
- <a href="{e2mMetadata['documentation']}">{e2mMetadata['documentation']}</a></b>
107
- </br>
108
- </p>
109
- <p style="text-align:center">
110
- This project is maintained by {e2mMetadata['author']}.
111
- <br>
112
- Development takes place at <a href="{e2mMetadata['homepage']}"> GitLab: {e2mMetadata['homepage']}</a>
113
- contributions are very welcome
114
- </br>
115
- If you encounter any issues please report them under the repositories issues page.
116
- </br>
117
- </p>
118
- <p style="text-align:center">
119
- <i>This project is published under {e2mMetadata['license']}, you are welcome, to share, modify and reuse the code.</i>
120
- </p>
121
- """
122
- QtWidgets.QMessageBox.information(
123
- self, f"About {e2mMetadata['name']}", aboutMessage
124
- )
125
-
126
- def closeEvent(self, event):
106
+ def closeEvent(self, event) -> None:
127
107
  self.settings.setValue("windowSize", self.size())
128
108
  self.settings.setValue("windowPosition", self.pos())
129
109
 
130
110
  @QtCore.Slot()
131
- def onSelectionChanged(self, item, col):
132
- """Whenever the selection changes the total of selected points needs to be recalculated"""
133
-
111
+ def onSelectionChanged(self, **args) -> None:
112
+ """Whenever the selection changes the total of selected points needs to be recalculated."""
134
113
  count: int = 0
135
114
  questions: int = 0
136
115
  selection = self.ui.treeWidget.selectedItems()
@@ -138,17 +117,13 @@ class MainWindow(QtWidgets.QMainWindow):
138
117
  questions += 1
139
118
  count += q.getQuestion().points
140
119
 
141
- logger.info(f"{questions} questions are selected with {count} points")
120
+ logger.info("%s questions are selected with %s points", questions, count)
142
121
  self.ui.pointCounter.setValue(count)
143
122
  self.ui.questionCounter.setValue(questions)
144
- return None
145
123
 
146
124
  @QtCore.Slot()
147
- def toggleQuestionSelectionState(self, state):
148
- if state == Qt.Checked:
149
- setter = True
150
- else:
151
- setter = False
125
+ def toggleQuestionSelectionState(self, state) -> None:
126
+ setter = state == Qt.Checked
152
127
  root = self.ui.treeWidget.invisibleRootItem()
153
128
  childN = root.childCount()
154
129
  for i in range(childN):
@@ -158,21 +133,20 @@ class MainWindow(QtWidgets.QMainWindow):
158
133
 
159
134
  @QtCore.Slot()
160
135
  def onButGenTest(self) -> None:
136
+ """Open a file Dialog so the export file may be choosen."""
161
137
  path = QtWidgets.QFileDialog.getSaveFileName(
162
138
  self,
163
139
  "Select Output File",
164
- dir=f"{
165
- self.mainPath/"Testfile.xml"}",
140
+ dir=f"{self.mainPath / 'Testfile.xml'}",
166
141
  filter="xml Files (*.xml)",
167
142
  )
168
143
  self.exportFile = Path(path[0])
169
- logger.info(f"New Export File is set{self.exportFile=}")
144
+ logger.info("New Export File is set %s", self.exportFile)
170
145
  selection: list[QuestionItem] = self.ui.treeWidget.selectedItems()
171
146
  self.testDB.appendQuestions(selection, self.exportFile)
172
- return None
173
147
 
174
148
  @QtCore.Slot()
175
- def onButSpreadsheet(self):
149
+ def onButSpreadsheet(self) -> None:
176
150
  file = QtWidgets.QFileDialog.getOpenFileName(
177
151
  self,
178
152
  self.tr("Open Spreadsheet"),
@@ -184,19 +158,25 @@ class MainWindow(QtWidgets.QMainWindow):
184
158
  self.settings.setSpreadsheet(self.excelPath)
185
159
  logger.debug(f"Saved Spreadsheet Path: {self.excelPath}\n")
186
160
  self.setStatus("[OK] Excel Tabelle wurde eingelesen")
187
- return None
188
161
 
189
162
  @QtCore.Slot()
190
163
  def onParseAll(self) -> None:
191
- """Event triggered by the *Tools/Parse all Questions* Event
164
+ """Event triggered by the *Tools/Parse all Questions* Event.
192
165
 
193
- It parses all the Questions found in the spreadsheet and then refreshes the list of questions.
166
+ It parses all the Questions found in the spreadsheet
167
+ and then refreshes the list of questions.
194
168
  If successful it prints out a list of all exported Questions
195
169
  """
196
- self.ui.buttonTestGen.setEnabled(True)
170
+ self.testDB.readSpreadsheetData(self.spreadSheetPath)
197
171
  self.testDB.parseAll()
198
172
  self.setStatus("[OK] Alle Fragen wurden erfolgreich in XML-Dateien umgewandelt")
199
- # below is former refres method
173
+ self.refreshList()
174
+
175
+ def refreshList(self) -> None:
176
+ """Refresh the question overview in the main window.
177
+
178
+ Enable the export Button afterwards.
179
+ """
200
180
  logger.info("starting List refresh")
201
181
  cats = self.testDB.categories
202
182
  self.ui.treeWidget.clear()
@@ -206,49 +186,54 @@ class MainWindow(QtWidgets.QMainWindow):
206
186
  for q in cat.questions.values():
207
187
  QuestionItem(catItem, q)
208
188
  self.setStatus("[OK] Fragen Liste wurde aktualisiert")
209
- return None
189
+ self.ui.buttonTestGen.setEnabled(True)
210
190
 
211
191
  @QtCore.Slot()
212
- def previewQ(self) -> None:
192
+ def openPreviewQuestionDlg(self) -> None:
213
193
  item = self.ui.treeWidget.currentItem()
214
194
  if isinstance(item, QuestionItem):
215
195
  dialog = dialogs.QuestinoPreviewDialog(self, item.getQuestion())
216
196
  dialog.show()
217
197
  else:
218
- logger.info(f"current Item is not a Question, can't preview")
198
+ logger.info("current Item is not a Question, can't preview")
219
199
 
220
- def setStatus(self, status):
200
+ def setStatus(self, status) -> None:
221
201
  self.ui.statusbar.clearMessage()
222
202
  self.ui.statusbar.showMessage(self.tr(status))
223
203
 
224
204
  @QtCore.Slot()
225
- def onButOpenEqChecker(self):
226
- logger.debug(f"opening wEquationChecker \n")
205
+ def openEqCheckerDlg(self) -> None:
206
+ logger.debug("opening wEquationChecker \n")
227
207
  self.uiEqChecker = EqCheckerWindow()
228
208
  self.uiEqChecker.excelFile = self.excelPath
229
209
  self.uiEqChecker.show()
230
210
 
211
+ @QtCore.Slot()
212
+ def openAboutDlg(self) -> None:
213
+ about = dialogs.AboutDialog(self)
214
+ about.exec()
215
+
231
216
 
232
217
  class EqCheckerWindow(QtWidgets.QWidget):
233
- def __init__(self):
218
+ def __init__(self) -> None:
234
219
  super().__init__()
235
220
  self.excelFile = Path()
236
221
  self.ui = Ui_EquationChecker()
237
222
  self.ui.setupUi(self)
238
223
  self.ui.buttonRunCheck.clicked.connect(
239
224
  lambda: self.onButRunCheck(
240
- self.ui.catNumber.value(), self.ui.qNumber.value()
241
- )
225
+ self.ui.catNumber.value(),
226
+ self.ui.qNumber.value(),
227
+ ),
242
228
  )
243
229
 
244
230
  def onButRunCheck(self, catN: int, qN: int) -> None:
245
- """
246
- Is Triggered by the ``Run Check now`` Button and runs the Equation Check
247
- """
248
-
231
+ """Is Triggered by the ``Run Check now`` Button and runs the Equation Check."""
249
232
  self.ui.textResultsOutput.clear()
250
233
  bullets, results, firstResult = eqVerif.equationChecker(
251
- f"KAT_{catN}", qN, self.excelFile
234
+ f"KAT_{catN}",
235
+ qN,
236
+ self.excelFile,
252
237
  )
253
238
  check = False
254
239
  self.ui.lineFirstResult.setText(f"{firstResult}")
@@ -257,13 +242,13 @@ class EqCheckerWindow(QtWidgets.QWidget):
257
242
  check = eqVerif.checkResult(firstResult, calculation)
258
243
  self.ui.lineCalculatedRes.setText(f"{calculation}")
259
244
  self.ui.textResultsOutput.append(
260
- f"Ergebnis {i+1}: \t{calculation}\n\tMit den Werten: \n{bullets[i]}\n"
245
+ f"Ergebnis {i + 1}: \t{calculation}\n\tMit den Werten: \n{bullets[i]}\n",
261
246
  )
262
247
 
263
- if check == True:
248
+ if check:
264
249
  self.ui.lineCheckResult.setText("[OK]")
265
250
  logger.info(
266
- f"Das erste berechnete Ergebnis stimmt mit dem Wert in 'firstResult' überein\n"
251
+ "Das erste berechnete Ergebnis stimmt mit dem Wert in 'firstResult' überein\n",
267
252
  )
268
253
  else:
269
254
  self.ui.lineCheckResult.setText("[ERROR]")
@@ -1,9 +1,10 @@
1
- """This Module hosts the various Dialog Classes, that can be shown from main Window"""
1
+ """This Module hosts the various Dialog Classes, that can be shown from main Window."""
2
2
 
3
3
  import lxml.etree as ET
4
4
  from PySide6 import QtGui, QtWidgets
5
5
  from PySide6.QtSvgWidgets import QGraphicsSvgItem
6
6
 
7
+ from excel2moodle import e2mMetadata
7
8
  from excel2moodle.core.globals import XMLTags
8
9
  from excel2moodle.core.question import Question
9
10
  from excel2moodle.ui.questionPreviewDialog import Ui_QuestionPrevDialog
@@ -11,7 +12,7 @@ from excel2moodle.ui.variantDialog import Ui_Dialog
11
12
 
12
13
 
13
14
  class QuestionVariantDialog(QtWidgets.QDialog):
14
- def __init__(self, parent, question: Question):
15
+ def __init__(self, parent, question: Question) -> None:
15
16
  super().__init__(parent)
16
17
  self.setWindowTitle("Question Variant Dialog")
17
18
  self.maxVal = question.variants
@@ -37,6 +38,7 @@ class QuestinoPreviewDialog(QtWidgets.QDialog):
37
38
  self.question = question
38
39
  self.ui = Ui_QuestionPrevDialog()
39
40
  self.ui.setupUi(self)
41
+ self.setModal(True)
40
42
  self.setWindowTitle(f"Question - {question.id} - Preview")
41
43
  self.setupQuestion()
42
44
 
@@ -81,13 +83,13 @@ class QuestinoPreviewDialog(QtWidgets.QDialog):
81
83
  for i, ans in enumerate(self.question.answerVariants):
82
84
  a = ans.find("text").text
83
85
  text = QtWidgets.QLineEdit(a, self)
84
- self.ui.answersFormLayout.addRow(f"Answer {i+1}", text)
86
+ self.ui.answersFormLayout.addRow(f"Answer {i + 1}", text)
85
87
 
86
88
  elif self.question.qtype == "NF":
87
89
  ans = self.question.element.find(XMLTags.ANSWER)
88
90
  a = ans.find("text").text
89
91
  text = QtWidgets.QLineEdit(a, self)
90
- self.ui.answersFormLayout.addRow(f"Result", text)
92
+ self.ui.answersFormLayout.addRow("Result", text)
91
93
 
92
94
  elif self.question.qtype == "MC":
93
95
  for i, ans in enumerate(self.question.element.findall(XMLTags.ANSWER)):
@@ -95,3 +97,37 @@ class QuestinoPreviewDialog(QtWidgets.QDialog):
95
97
  frac = ans.get("fraction")
96
98
  text = QtWidgets.QLineEdit(a, self)
97
99
  self.ui.answersFormLayout.addRow(f"Fraction: {frac}", text)
100
+
101
+
102
+ class AboutDialog(QtWidgets.QMessageBox):
103
+ def __init__(self, parent: QtWidgets.QWidget) -> None:
104
+ super().__init__(parent)
105
+ self.setWindowTitle(f"About {e2mMetadata['name']}")
106
+ self.setIcon(QtWidgets.QMessageBox.Information)
107
+ self.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Close)
108
+
109
+ self.aboutMessage: str = f"""
110
+ <h1> About {e2mMetadata["name"]}</h1><br>
111
+ <p style="text-align:center">
112
+
113
+ <b><a href="{e2mMetadata["homepage"]}">{e2mMetadata["name"]}</a> - {e2mMetadata["description"]}</b>
114
+ </p>
115
+ <p style="text-align:center">
116
+ The documentation can be found under <b>
117
+ <a href="{e2mMetadata["documentation"]}">{e2mMetadata["documentation"]}</a></b>
118
+ </br>
119
+ </p>
120
+ <p style="text-align:center">
121
+ This project is maintained by {e2mMetadata["author"]}.
122
+ <br>
123
+ Development takes place at <a href="{e2mMetadata["homepage"]}"> GitLab: {e2mMetadata["homepage"]}</a>
124
+ contributions are very welcome
125
+ </br>
126
+ If you encounter any issues please report them under the repositories issues page.
127
+ </br>
128
+ </p>
129
+ <p style="text-align:center">
130
+ <i>This project is published under {e2mMetadata["license"]}, you are welcome, to share, modify and reuse the code.</i>
131
+ </p>
132
+ """
133
+ self.setText(self.aboutMessage)