excel2moodle 0.4.1__py3-none-any.whl → 0.4.3__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.
Files changed (34) hide show
  1. excel2moodle/__init__.py +0 -7
  2. excel2moodle/__main__.py +2 -2
  3. excel2moodle/core/__init__.py +0 -10
  4. excel2moodle/core/category.py +4 -3
  5. excel2moodle/core/dataStructure.py +116 -61
  6. excel2moodle/core/etHelpers.py +2 -2
  7. excel2moodle/core/exceptions.py +2 -2
  8. excel2moodle/core/globals.py +10 -27
  9. excel2moodle/core/parser.py +24 -30
  10. excel2moodle/core/question.py +147 -63
  11. excel2moodle/core/settings.py +107 -111
  12. excel2moodle/core/validator.py +36 -55
  13. excel2moodle/logger.py +7 -4
  14. excel2moodle/question_types/__init__.py +2 -0
  15. excel2moodle/question_types/cloze.py +207 -0
  16. excel2moodle/question_types/mc.py +26 -16
  17. excel2moodle/question_types/nf.py +17 -3
  18. excel2moodle/question_types/nfm.py +60 -17
  19. excel2moodle/ui/{windowEquationChecker.py → UI_equationChecker.py} +98 -78
  20. excel2moodle/ui/{exportSettingsDialog.py → UI_exportSettingsDialog.py} +55 -4
  21. excel2moodle/ui/{windowMain.py → UI_mainWindow.py} +32 -39
  22. excel2moodle/ui/appUi.py +66 -86
  23. excel2moodle/ui/dialogs.py +40 -2
  24. excel2moodle/ui/equationChecker.py +70 -0
  25. excel2moodle/ui/treewidget.py +4 -4
  26. {excel2moodle-0.4.1.dist-info → excel2moodle-0.4.3.dist-info}/METADATA +2 -3
  27. excel2moodle-0.4.3.dist-info/RECORD +38 -0
  28. {excel2moodle-0.4.1.dist-info → excel2moodle-0.4.3.dist-info}/entry_points.txt +0 -3
  29. excel2moodle/ui/questionPreviewDialog.py +0 -115
  30. excel2moodle-0.4.1.dist-info/RECORD +0 -37
  31. /excel2moodle/ui/{variantDialog.py → UI_variantDialog.py} +0 -0
  32. {excel2moodle-0.4.1.dist-info → excel2moodle-0.4.3.dist-info}/WHEEL +0 -0
  33. {excel2moodle-0.4.1.dist-info → excel2moodle-0.4.3.dist-info}/licenses/LICENSE +0 -0
  34. {excel2moodle-0.4.1.dist-info → excel2moodle-0.4.3.dist-info}/top_level.txt +0 -0
excel2moodle/ui/appUi.py CHANGED
@@ -8,20 +8,20 @@ import logging
8
8
  from pathlib import Path
9
9
 
10
10
  from PySide6 import QtCore, QtWidgets
11
- from PySide6.QtCore import QRunnable, Qt, QThreadPool
11
+ from PySide6.QtCore import QRunnable, QSettings, Qt, QThreadPool
12
12
 
13
13
  from excel2moodle import mainLogger
14
14
  from excel2moodle.core.category import Category
15
15
  from excel2moodle.core.dataStructure import QuestionDB
16
- from excel2moodle.core.settings import Settings, SettingsKey
17
- from excel2moodle.extra import equationVerification as eqVerif
16
+ from excel2moodle.core.settings import Settings, Tags
18
17
  from excel2moodle.logger import LogWindowHandler
18
+ from excel2moodle.question_types.mc import MCQuestion
19
+ from excel2moodle.question_types.nf import NFQuestion
19
20
  from excel2moodle.ui import dialogs
21
+ from excel2moodle.ui.equationChecker import EqCheckerWindow
20
22
  from excel2moodle.ui.treewidget import CategoryItem, QuestionItem
23
+ from excel2moodle.ui.UI_mainWindow import Ui_MoodleTestGenerator
21
24
  from excel2moodle.ui.windowDoc import DocumentationWindow
22
- from excel2moodle.ui.windowMain import Ui_MoodleTestGenerator
23
-
24
- from .windowEquationChecker import Ui_EquationChecker
25
25
 
26
26
  logger = logging.getLogger(__name__)
27
27
 
@@ -33,6 +33,9 @@ class MainWindow(QtWidgets.QMainWindow):
33
33
  def __init__(self, settings: Settings, testDB: QuestionDB) -> None:
34
34
  super().__init__()
35
35
  self.settings = settings
36
+ self.qSettings = QSettings("jbosse3", "excel2moodle")
37
+ logger.info("Settings are stored under: %s", self.qSettings.fileName())
38
+
36
39
  self.excelPath: Path | None = None
37
40
  self.mainPath = self.excelPath.parent if self.excelPath is not None else None
38
41
  self.exportFile = Path()
@@ -41,17 +44,18 @@ class MainWindow(QtWidgets.QMainWindow):
41
44
  self.ui.setupUi(self)
42
45
  self.exportDialog = dialogs.ExportDialog(self)
43
46
  self.questionPreview = dialogs.QuestionPreview(self)
47
+ self.eqChecker = EqCheckerWindow()
44
48
  self.connectEvents()
45
- logger.info("Settings are stored under: %s", self.settings.fileName())
49
+ logger.info("Settings are stored under: %s", self.qSettings.fileName())
46
50
  self.ui.treeWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
47
51
  self.ui.treeWidget.header().setSectionResizeMode(
48
52
  QtWidgets.QHeaderView.ResizeToContents,
49
53
  )
50
54
  self.exportDialog.ui.checkBoxIncludeCategories.setChecked(
51
- self.settings.get(SettingsKey.INCLUDEINCATS),
55
+ self.qSettings.value(Tags.INCLUDEINCATS, defaultValue=True, type=bool)
52
56
  )
53
57
  self.exportDialog.ui.spinBoxDefaultQVariant.setValue(
54
- self.settings.get(SettingsKey.QUESTIONVARIANT)
58
+ self.qSettings.value(Tags.QUESTIONVARIANT, defaultValue=1, type=int)
55
59
  )
56
60
  self.ui.pointCounter.setReadOnly(True)
57
61
  self.ui.questionCounter.setReadOnly(True)
@@ -59,11 +63,14 @@ class MainWindow(QtWidgets.QMainWindow):
59
63
  "Wählen Sie eine Excel Tabelle mit den Fragen aus",
60
64
  )
61
65
  try:
62
- self.resize(self.settings.value("windowSize"))
63
- self.move(self.settings.value("windowPosition"))
66
+ self.resize(self.qSettings.value("windowSize"))
67
+ self.move(self.qSettings.value("windowPosition"))
64
68
  except Exception:
65
69
  pass
66
70
  self.threadPool = QThreadPool()
71
+ if self.qSettings.contains(Tags.SPREADSHEETPATH.full):
72
+ sheet = self.qSettings.value(Tags.SPREADSHEETPATH.full)
73
+ self.setSheetPath(sheet)
67
74
 
68
75
  def connectEvents(self) -> None:
69
76
  self.ui.treeWidget.itemSelectionChanged.connect(self.onSelectionChanged)
@@ -84,14 +91,13 @@ class MainWindow(QtWidgets.QMainWindow):
84
91
  self.ui.treeWidget.itemClicked.connect(self.updateQuestionPreview)
85
92
  self.ui.actionAbout.triggered.connect(self.openAboutDlg)
86
93
  self.ui.actionDocumentation.triggered.connect(self.openDocumentation)
87
- self.settings.shPathChanged.connect(self.onSheetPathChanged)
88
94
  self.exportDialog.ui.spinBoxDefaultQVariant.valueChanged.connect(
89
95
  self.setQVariantDefault
90
96
  )
91
97
 
92
98
  @QtCore.Slot()
93
99
  def setQVariantDefault(self, value: int) -> None:
94
- self.settings.set(SettingsKey.QUESTIONVARIANT, value)
100
+ self.settings.set(Tags.QUESTIONVARIANT, value)
95
101
 
96
102
  @QtCore.Slot()
97
103
  def parseSpreadsheetAll(self) -> None:
@@ -102,32 +108,44 @@ class MainWindow(QtWidgets.QMainWindow):
102
108
  If successful it prints out a list of all exported Questions
103
109
  """
104
110
  self.ui.treeWidget.clear()
111
+ self.testDB.readCategoriesMetadata()
105
112
  process = ParseAllThread(self.testDB, self)
106
113
  self.threadPool.start(process)
107
114
 
108
- @QtCore.Slot(Path)
109
- def onSheetPathChanged(self, sheet: Path) -> None:
110
- logger.debug("Slot, new Spreadsheet triggered")
111
- self.spreadSheetPath = sheet
115
+ def setSheetPath(self, sheet: Path) -> None:
116
+ logger.debug("Received new spreadsheet.")
117
+ if not sheet.is_file():
118
+ logger.warning("Sheet is not a file")
119
+ self.setStatus("[ERROR] keine Tabelle angegeben")
120
+ return
121
+ self.excelPath = sheet
112
122
  self.mainPath = sheet.parent
113
- svgFolder = self.mainPath / self.settings.get(SettingsKey.PICTURESUBFOLDER)
114
- svgFolder.resolve()
115
- self.settings.set(SettingsKey.PICTUREFOLDER, svgFolder)
116
123
  self.ui.buttonSpreadsheet.setText(f"../{sheet.name}")
124
+ self.testDB.spreadsheet = sheet
125
+ self.qSettings.setValue(Tags.SPREADSHEETPATH.full, sheet)
117
126
  self.parseSpreadsheetAll()
127
+ self.setStatus("[OK] Excel Tabelle wurde eingelesen")
118
128
 
119
129
  def updateLog(self, log) -> None:
120
130
  self.ui.loggerWindow.append(log)
121
131
 
122
132
  def setIncludeCategoriesSetting(self) -> None:
123
133
  if self.exportDialog.ui.checkBoxIncludeCategories.isChecked():
124
- self.settings.set(SettingsKey.INCLUDEINCATS, True)
134
+ self.settings.set(Tags.INCLUDEINCATS, True)
125
135
  else:
126
- self.settings.set(SettingsKey.INCLUDEINCATS, False)
136
+ self.settings.set(Tags.INCLUDEINCATS, False)
127
137
 
128
138
  def closeEvent(self, event) -> None:
129
- self.settings.setValue("windowSize", self.size())
130
- self.settings.setValue("windowPosition", self.pos())
139
+ logger.info("Closing. Saving window stats.")
140
+ self.qSettings.setValue("windowSize", self.size())
141
+ self.qSettings.setValue("windowPosition", self.pos())
142
+ self.qSettings.setValue(
143
+ Tags.INCLUDEINCATS, self.settings.get(Tags.INCLUDEINCATS)
144
+ )
145
+ self.qSettings.setValue(
146
+ Tags.QUESTIONVARIANT,
147
+ self.settings.get(Tags.QUESTIONVARIANT),
148
+ )
131
149
 
132
150
  @QtCore.Slot()
133
151
  def onSelectionChanged(self, **args) -> None:
@@ -140,6 +158,8 @@ class MainWindow(QtWidgets.QMainWindow):
140
158
  count += q.getQuestion().points
141
159
  self.ui.pointCounter.setValue(count)
142
160
  self.ui.questionCounter.setValue(questions)
161
+ if self.eqChecker.isVisible():
162
+ self.openEqCheckerDlg()
143
163
 
144
164
  @QtCore.Slot()
145
165
  def toggleQuestionSelectionState(self, state) -> None:
@@ -154,17 +174,16 @@ class MainWindow(QtWidgets.QMainWindow):
154
174
  @QtCore.Slot()
155
175
  def onButGenTest(self) -> None:
156
176
  """Open a file Dialog so the export file may be choosen."""
157
- self.exportDialog.exec()
158
- path = QtWidgets.QFileDialog.getSaveFileName(
159
- self,
160
- "Select Output File",
161
- dir=f"{self.mainPath / 'Testfile.xml'}",
162
- filter="xml Files (*.xml)",
163
- )
164
- self.exportFile = Path(path[0])
165
- logger.info("New Export File is set %s", self.exportFile)
166
177
  selection: list[QuestionItem] = self.ui.treeWidget.selectedItems()
167
- self.testDB.appendQuestions(selection, self.exportFile)
178
+ self.exportDialog.exportFile = Path(self.mainPath / "TestFile.xml")
179
+ self.exportDialog.ui.questionCount.setValue(self.ui.questionCounter.value())
180
+ self.exportDialog.ui.pointCount.setValue(self.ui.pointCounter.value())
181
+ if self.exportDialog.exec():
182
+ self.exportFile = self.exportDialog.exportFile
183
+ logger.info("New Export File is set %s", self.exportFile)
184
+ self.testDB.appendQuestions(selection, self.exportFile)
185
+ else:
186
+ logger.info("Aborting Export")
168
187
 
169
188
  @QtCore.Slot()
170
189
  def actionSpreadsheet(self) -> None:
@@ -176,12 +195,7 @@ class MainWindow(QtWidgets.QMainWindow):
176
195
  selectedFilter=("*.ods"),
177
196
  )
178
197
  path = Path(file[0]).resolve(strict=True)
179
- if path.is_file():
180
- self.excelPath = path
181
- self.settings.setSpreadsheet(self.excelPath)
182
- self.setStatus("[OK] Excel Tabelle wurde eingelesen")
183
- else:
184
- self.setStatus("[ERROR] keine Tabelle angegeben")
198
+ self.setSheetPath(path)
185
199
 
186
200
  @QtCore.Slot(Category)
187
201
  def treeRefreshCategory(self, cat: Category) -> None:
@@ -206,10 +220,17 @@ class MainWindow(QtWidgets.QMainWindow):
206
220
 
207
221
  @QtCore.Slot()
208
222
  def openEqCheckerDlg(self) -> None:
209
- logger.debug("opening wEquationChecker \n")
210
- self.uiEqChecker = EqCheckerWindow()
211
- self.uiEqChecker.excelFile = self.excelPath
212
- self.uiEqChecker.show()
223
+ item = self.ui.treeWidget.currentItem()
224
+ if isinstance(item, QuestionItem):
225
+ question = item.getQuestion()
226
+ if isinstance(question, (NFQuestion, MCQuestion)):
227
+ logger.debug("Can't check an MC or NF Question")
228
+ else:
229
+ logger.debug("opening wEquationChecker \n")
230
+ self.eqChecker.setup(item.getQuestion())
231
+ self.eqChecker.show()
232
+ else:
233
+ logger.debug("No Question Item selected: %s", type(item))
213
234
 
214
235
  @QtCore.Slot()
215
236
  def openAboutDlg(self) -> None:
@@ -238,47 +259,6 @@ class ParseAllThread(QRunnable):
238
259
 
239
260
  @QtCore.Slot()
240
261
  def run(self) -> None:
241
- self.testDB.readCategoriesMetadata(self.mainApp.spreadSheetPath)
242
- self.testDB.asyncInitAllCategories(self.mainApp.spreadSheetPath)
262
+ self.testDB.asyncInitAllCategories(self.mainApp.excelPath)
243
263
  self.mainApp.setStatus("[OK] Tabellen wurde eingelesen")
244
264
  self.testDB.parseAllQuestions()
245
-
246
-
247
- class EqCheckerWindow(QtWidgets.QWidget):
248
- def __init__(self) -> None:
249
- super().__init__()
250
- self.excelFile = Path()
251
- self.ui = Ui_EquationChecker()
252
- self.ui.setupUi(self)
253
- self.ui.buttonRunCheck.clicked.connect(
254
- lambda: self.onButRunCheck(
255
- self.ui.catNumber.value(),
256
- self.ui.qNumber.value(),
257
- ),
258
- )
259
-
260
- def onButRunCheck(self, catN: int, qN: int) -> None:
261
- """Is Triggered by the ``Run Check now`` Button and runs the Equation Check."""
262
- self.ui.textResultsOutput.clear()
263
- bullets, results, firstResult = eqVerif.equationChecker(
264
- f"KAT_{catN}",
265
- qN,
266
- self.excelFile,
267
- )
268
- check = False
269
- self.ui.lineFirstResult.setText(f"{firstResult}")
270
- for i, calculation in enumerate(results):
271
- if i == 0 and firstResult != 0:
272
- check = eqVerif.checkResult(firstResult, calculation)
273
- self.ui.lineCalculatedRes.setText(f"{calculation}")
274
- self.ui.textResultsOutput.append(
275
- f"Ergebnis {i + 1}: \t{calculation}\n\tMit den Werten: \n{bullets[i]}\n",
276
- )
277
-
278
- if check:
279
- self.ui.lineCheckResult.setText("[OK]")
280
- logger.info(
281
- "Das erste berechnete Ergebnis stimmt mit dem Wert in 'firstResult' überein\n",
282
- )
283
- else:
284
- self.ui.lineCheckResult.setText("[ERROR]")
@@ -1,5 +1,9 @@
1
1
  """This Module hosts the various Dialog Classes, that can be shown from main Window."""
2
2
 
3
+ import logging
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING
6
+
3
7
  import lxml.etree as ET
4
8
  from PySide6 import QtGui, QtWidgets
5
9
  from PySide6.QtSvgWidgets import QGraphicsSvgItem
@@ -7,8 +11,13 @@ from PySide6.QtSvgWidgets import QGraphicsSvgItem
7
11
  from excel2moodle import e2mMetadata
8
12
  from excel2moodle.core.globals import XMLTags
9
13
  from excel2moodle.core.question import Question
10
- from excel2moodle.ui.exportSettingsDialog import Ui_ExportDialog
11
- from excel2moodle.ui.variantDialog import Ui_Dialog
14
+ from excel2moodle.ui.UI_exportSettingsDialog import Ui_ExportDialog
15
+ from excel2moodle.ui.UI_variantDialog import Ui_Dialog
16
+
17
+ if TYPE_CHECKING:
18
+ from excel2moodle.ui.appUi import MainWindow
19
+
20
+ logger = logging.getLogger(__name__)
12
21
 
13
22
 
14
23
  class QuestionVariantDialog(QtWidgets.QDialog):
@@ -36,8 +45,37 @@ class ExportDialog(QtWidgets.QDialog):
36
45
  def __init__(self, parent) -> None:
37
46
  super().__init__(parent)
38
47
  self.setWindowTitle("Export question Selection")
48
+ self.appUi: MainWindow = parent
39
49
  self.ui = Ui_ExportDialog()
40
50
  self.ui.setupUi(self)
51
+ self.ui.btnExportFile.clicked.connect(self.getExportFile)
52
+
53
+ @property
54
+ def exportFile(self) -> Path:
55
+ return self._exportFile
56
+
57
+ @exportFile.setter
58
+ def exportFile(self, value: Path) -> None:
59
+ self._exportFile = value
60
+ self.ui.btnExportFile.setText(
61
+ f"../{(self.exportFile.parent.name)}/{self.exportFile.name}"
62
+ )
63
+
64
+ def getExportFile(self) -> None:
65
+ path = QtWidgets.QFileDialog.getSaveFileName(
66
+ self,
67
+ "Select Output File",
68
+ dir=str(self.exportFile),
69
+ filter="xml Files (*.xml)",
70
+ )
71
+ path = Path(path[0])
72
+ if path.is_file():
73
+ self.exportFile = path
74
+ self.ui.btnExportFile.setText(
75
+ f"../{(self.exportFile.parent.name)}/{self.exportFile.name}"
76
+ )
77
+ else:
78
+ logger.warning("No Export File selected")
41
79
 
42
80
 
43
81
  class QuestionPreview:
@@ -0,0 +1,70 @@
1
+ import logging
2
+ import math
3
+ from pathlib import Path
4
+
5
+ from PySide6 import QtWidgets
6
+
7
+ from excel2moodle import mainLogger
8
+ from excel2moodle.core.question import ParametricQuestion
9
+ from excel2moodle.core.settings import Tags
10
+ from excel2moodle.logger import LogWindowHandler
11
+ from excel2moodle.question_types.nfm import NFMQuestionParser
12
+
13
+ from .UI_equationChecker import Ui_EquationChecker
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ loggerSignal = LogWindowHandler()
18
+ mainLogger.addHandler(loggerSignal)
19
+
20
+
21
+ class EqCheckerWindow(QtWidgets.QWidget):
22
+ def __init__(self) -> None:
23
+ super().__init__()
24
+ self.excelFile = Path()
25
+ self.ui = Ui_EquationChecker()
26
+ self.ui.setupUi(self)
27
+ self.ui.buttonRunCheck.clicked.connect(
28
+ lambda: self.updateCalculation(),
29
+ )
30
+ self.question: ParametricQuestion
31
+
32
+ def updateCalculation(self) -> None:
33
+ equation = self.ui.equationText.toPlainText()
34
+ results: list[float] = []
35
+ firstResult = self.question.rawData.get(Tags.FIRSTRESULT)
36
+ for i in range(self.question.variants):
37
+ NFMQuestionParser.setupAstIntprt(self.question.variables, i)
38
+ results.append(float(NFMQuestionParser.astEval(equation)))
39
+ check: bool = False
40
+ self.ui.textResultsOutput.insertHtml(f"<hr><br><h2>{equation:^30}</h2><br>")
41
+ for i, calculation in enumerate(results):
42
+ if i == 0 and firstResult != 0:
43
+ check = bool(math.isclose(calculation, firstResult, rel_tol=0.01))
44
+ self.ui.lineCalculatedRes.setText(f"{calculation}")
45
+ self.ui.textResultsOutput.append(f"<h3>Result {check = }</h3><br>")
46
+ self.ui.textResultsOutput.append(
47
+ f"Ergebnis {i + 1}: \t{calculation}",
48
+ )
49
+ if check:
50
+ self.ui.lineCheckResult.setText("[OK]")
51
+ logger.info(
52
+ " [OK] The first calculated result matches 'firstResult'",
53
+ )
54
+ else:
55
+ self.ui.lineCheckResult.setText("[ERROR]")
56
+ logger.warning(
57
+ "The first calculated result does not match 'firstResult'",
58
+ )
59
+
60
+ def setup(self, question: ParametricQuestion) -> None:
61
+ self.question = question
62
+ self.ui.textResultsOutput.clear()
63
+ self.ui.equationText.clear()
64
+ bullets = question.rawData.get(Tags.BPOINTS)
65
+ firstResult = question.rawData.get(Tags.FIRSTRESULT)
66
+ self.ui.lineFirstResult.setText(str(firstResult))
67
+ self.ui.equationText.appendPlainText(question.rawData.get(Tags.EQUATION))
68
+ for bullet in bullets:
69
+ self.ui.textResultsOutput.append(bullet)
70
+ self.updateCalculation()
@@ -2,11 +2,11 @@ from PySide6 import QtWidgets
2
2
  from PySide6.QtCore import Qt
3
3
 
4
4
  from excel2moodle.core.dataStructure import Category
5
- from excel2moodle.core.question import Question
5
+ from excel2moodle.core.question import ParametricQuestion, Question
6
6
 
7
7
 
8
8
  class QuestionItem(QtWidgets.QTreeWidgetItem):
9
- def __init__(self, parent, question: Question) -> None:
9
+ def __init__(self, parent, question: Question | ParametricQuestion) -> None:
10
10
  super().__init__(parent)
11
11
  self.setData(2, Qt.UserRole, question)
12
12
  self.setText(0, question.id)
@@ -15,7 +15,7 @@ class QuestionItem(QtWidgets.QTreeWidgetItem):
15
15
  if hasattr(question, "variants") and question.variants is not None:
16
16
  self.setText(3, str(question.variants))
17
17
 
18
- def getQuestion(self) -> Question:
18
+ def getQuestion(self) -> Question | ParametricQuestion:
19
19
  """Return the question Object the QTreeWidgetItem represents."""
20
20
  return self.data(2, Qt.UserRole)
21
21
 
@@ -40,7 +40,7 @@ class CategoryItem(QtWidgets.QTreeWidgetItem):
40
40
  for child in self.iterateChildren():
41
41
  q = child.getQuestion()
42
42
  if hasattr(q, "variants") and q.variants is not None:
43
- count = q.variants if count <= q.variants else count
43
+ count = max(q.variants, count)
44
44
  return count
45
45
 
46
46
  def getCategory(self) -> Category:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: excel2moodle
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Summary: A package for converting questions from a spreadsheet, to valid moodle-xml
5
5
  Author: Jakob Bosse
6
6
  License-Expression: GPL-3.0-or-later
@@ -14,10 +14,9 @@ Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: pyside6>=6.8.0
16
16
  Requires-Dist: pandas>=2.1.3
17
- Requires-Dist: openpyxl>=3.1.5
18
17
  Requires-Dist: lxml>=5.4.0
19
- Requires-Dist: odfpy>=1.4.1
20
18
  Requires-Dist: asteval>=1.0.6
19
+ Requires-Dist: python-calamine>=0.3.2
21
20
  Dynamic: license-file
22
21
 
23
22
  # excel 2 Moodle
@@ -0,0 +1,38 @@
1
+ excel2moodle/__init__.py,sha256=mnb-RWgmWIPSBk4S65a_jP6rxntAkTeYxN0ObUJalbQ,1801
2
+ excel2moodle/__main__.py,sha256=sG4ygwfVFskLQorBn-v98SvasNcPmwl_vLYpruT5Hk8,1175
3
+ excel2moodle/logger.py,sha256=S9tvSwsOx2xta_AhGKHPNgi5FaiycyUDtkzHlIlNAX8,3193
4
+ excel2moodle/core/__init__.py,sha256=87BwhtZse72Tk17Ib-V9X2k9wkhmtVnEj2ZmJ9JBAnI,63
5
+ excel2moodle/core/category.py,sha256=TzntDhEURshxWuI6qc_K_t5bSTLXn6s0n_RA56Basg8,1885
6
+ excel2moodle/core/dataStructure.py,sha256=Gg9dq4koJPAKj87YFItTCz8QlK743K8s_iflJjLWZyU,15535
7
+ excel2moodle/core/etHelpers.py,sha256=G37qplp8tPJxqHNCBrf2Wo0jJZ0aDbxE9slQavqYqd8,2293
8
+ excel2moodle/core/exceptions.py,sha256=9xfsaIcm6Yej6QAZga0d3DK3jLQejdfgJARuAaG-uZY,739
9
+ excel2moodle/core/globals.py,sha256=Zm1wcrzQTRnhjrkwgBvo7VjKCFdPMjh-VLSSI5_QCO8,2837
10
+ excel2moodle/core/numericMultiQ.py,sha256=vr-gYogu2sf2a_Bhvhnu1ZSZFZXM32MfhJesjTkoOQM,2618
11
+ excel2moodle/core/parser.py,sha256=Ec8bQ0CiiZCIdzQovfH2rce406wmyRmvhpDrCPeQfGU,8112
12
+ excel2moodle/core/question.py,sha256=nJDs8SPDRYP6xG4rvo8Bbh1734eQ96DZxVXb7yrT8LM,10802
13
+ excel2moodle/core/settings.py,sha256=JhcgZcOrgFC7P4h9fSXZAApEl_9dE643r5arFpU1HXQ,5808
14
+ excel2moodle/core/stringHelpers.py,sha256=OzFZ6Eu3PeBLKb61K-aeVfUZmVuBerr9KfyOsuNRd7Y,2403
15
+ excel2moodle/core/validator.py,sha256=RwDQ-9Fpc5i2Buy3oorWUAh5zsS5fCF-MjRT4CgcXhY,4698
16
+ excel2moodle/extra/__init__.py,sha256=PM-id60HD21A3IcGC_fCYFihS8osBGZMIJCcN-ZRsIM,293
17
+ excel2moodle/extra/equationVerification.py,sha256=GLJl1r90d8AAiNy0H2hooZrg3D6aEwNfifYKAe3aGxM,3921
18
+ excel2moodle/question_types/__init__.py,sha256=81mss0g7SVtnlb-WkydE28G_dEAAf6oT1uB8lpK2-II,1041
19
+ excel2moodle/question_types/cloze.py,sha256=hgyv244PChnl7FbxcAMQiC4yzBhV6J3Bg4PHgZQyRmQ,7677
20
+ excel2moodle/question_types/mc.py,sha256=rHKIKSNeHyto84bI9B3wMKzNJuluplsCmYM4k2HW3wQ,5213
21
+ excel2moodle/question_types/nf.py,sha256=bMP4IXrhnXmAI0NmjEc7DtX4xGaUbxzLicE2LjeaUho,1150
22
+ excel2moodle/question_types/nfm.py,sha256=VYrQmCsEZqfn0x_coBsDw3XvrUA4sy_yj0WS7Nsffqw,4950
23
+ excel2moodle/ui/UI_equationChecker.py,sha256=evQDlqCHeooJcAnYjhFCyjlPhfknr7ULGKQwMmqQeJ4,8947
24
+ excel2moodle/ui/UI_exportSettingsDialog.py,sha256=71xxXEqtewN0ReMfJ5t4gbrX_Bf0VEuxJ_DIV7ZtH94,6045
25
+ excel2moodle/ui/UI_mainWindow.py,sha256=asWUmKIYqufKUvRuCuA1JoMyv4qfRXyoR70F0331lww,19291
26
+ excel2moodle/ui/UI_variantDialog.py,sha256=snVaF3_YAc7NWjMRg7NzbjL_PzNbOpt4eiqElkE46io,5414
27
+ excel2moodle/ui/__init__.py,sha256=4EdGtpzwH3rgw4xW9E5x9kdPQYwKbo9rehHRZTNxCrQ,44
28
+ excel2moodle/ui/appUi.py,sha256=NXlBcjxHBeUzpU8rvqwN3wxad8AUgpMjXidwwVdC9GM,10863
29
+ excel2moodle/ui/dialogs.py,sha256=JbQ1y55wbzWVTY0nxdGrUm81AdOIY3PXKgET03Hc6Ys,6760
30
+ excel2moodle/ui/equationChecker.py,sha256=ANpN7S0llkp6pGL1sKHII1Jc8YUvgDR458UnGVnZZOo,2702
31
+ excel2moodle/ui/treewidget.py,sha256=az64swVj1yQUsioeaZys32AauvQDdC4EKcqdbbWgL6s,2489
32
+ excel2moodle/ui/windowDoc.py,sha256=WvzHj6F4JvHP82WlTsyFeOXW024Xq3BUqtp--T4twuI,661
33
+ excel2moodle-0.4.3.dist-info/licenses/LICENSE,sha256=ywQqe6Sitymkf2lV2NRcx_aGsaC-KbSl_EfEsRXmNRw,35135
34
+ excel2moodle-0.4.3.dist-info/METADATA,sha256=mFhUf8uf-GTxdpyOV1JJlb5bkA-fUqUYeHPea-LwMfw,2951
35
+ excel2moodle-0.4.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
+ excel2moodle-0.4.3.dist-info/entry_points.txt,sha256=myfMLDThuGgWHMJDPPfILiZqo_7D3fhmDdJGqWOAjPw,60
37
+ excel2moodle-0.4.3.dist-info/top_level.txt,sha256=5V1xRUQ9o7UmOCmNoWCZPAuy5nXp3Qbzyqch8fUGT_c,13
38
+ excel2moodle-0.4.3.dist-info/RECORD,,
@@ -1,5 +1,2 @@
1
1
  [console_scripts]
2
2
  excel2moodle = excel2moodle.__main__:main
3
-
4
- [gui_scripts]
5
- excel2moodle = excel2moodle.__main__:main
@@ -1,115 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- ################################################################################
4
- ## Form generated from reading UI file 'questionPreviewDialog.ui'
5
- ##
6
- ## Created by: Qt User Interface Compiler version 6.8.1
7
- ##
8
- ## WARNING! All changes made in this file will be lost when recompiling UI file!
9
- ################################################################################
10
-
11
- from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
12
- QMetaObject, QObject, QPoint, QRect,
13
- QSize, QTime, QUrl, Qt)
14
- from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
15
- QFont, QFontDatabase, QGradient, QIcon,
16
- QImage, QKeySequence, QLinearGradient, QPainter,
17
- QPalette, QPixmap, QRadialGradient, QTransform)
18
- from PySide6.QtWidgets import (QAbstractButton, QApplication, QDialog, QDialogButtonBox,
19
- QFormLayout, QFrame, QGraphicsView, QLabel,
20
- QLineEdit, QSizePolicy, QVBoxLayout, QWidget)
21
-
22
- class Ui_QuestionPrevDialog(object):
23
- def setupUi(self, QuestionPrevDialog):
24
- if not QuestionPrevDialog.objectName():
25
- QuestionPrevDialog.setObjectName(u"QuestionPrevDialog")
26
- QuestionPrevDialog.resize(577, 620)
27
- self.verticalLayout = QVBoxLayout(QuestionPrevDialog)
28
- self.verticalLayout.setObjectName(u"verticalLayout")
29
- self.formLayout = QFormLayout()
30
- self.formLayout.setObjectName(u"formLayout")
31
- self.formLayout.setLabelAlignment(Qt.AlignmentFlag.AlignLeading|Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignVCenter)
32
- self.formLayout.setHorizontalSpacing(20)
33
- self.formLayout.setVerticalSpacing(5)
34
- self.formLayout.setContentsMargins(10, 6, 10, -1)
35
- self.questionNameLabel = QLabel(QuestionPrevDialog)
36
- self.questionNameLabel.setObjectName(u"questionNameLabel")
37
-
38
- self.formLayout.setWidget(0, QFormLayout.LabelRole, self.questionNameLabel)
39
-
40
- self.qNameLine = QLineEdit(QuestionPrevDialog)
41
- self.qNameLine.setObjectName(u"qNameLine")
42
- self.qNameLine.setReadOnly(True)
43
-
44
- self.formLayout.setWidget(0, QFormLayout.FieldRole, self.qNameLine)
45
-
46
- self.label = QLabel(QuestionPrevDialog)
47
- self.label.setObjectName(u"label")
48
-
49
- self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label)
50
-
51
- self.qTypeLine = QLineEdit(QuestionPrevDialog)
52
- self.qTypeLine.setObjectName(u"qTypeLine")
53
- self.qTypeLine.setReadOnly(True)
54
-
55
- self.formLayout.setWidget(1, QFormLayout.FieldRole, self.qTypeLine)
56
-
57
-
58
- self.verticalLayout.addLayout(self.formLayout)
59
-
60
- self.line = QFrame(QuestionPrevDialog)
61
- self.line.setObjectName(u"line")
62
- self.line.setFrameShape(QFrame.Shape.HLine)
63
- self.line.setFrameShadow(QFrame.Shadow.Sunken)
64
-
65
- self.verticalLayout.addWidget(self.line)
66
-
67
- self.questionText = QLabel(QuestionPrevDialog)
68
- self.questionText.setObjectName(u"questionText")
69
- self.questionText.setWordWrap(True)
70
- self.questionText.setMargin(10)
71
-
72
- self.verticalLayout.addWidget(self.questionText)
73
-
74
- self.graphicsView = QGraphicsView(QuestionPrevDialog)
75
- self.graphicsView.setObjectName(u"graphicsView")
76
- brush = QBrush(QColor(231, 243, 245, 255))
77
- brush.setStyle(Qt.SolidPattern)
78
- self.graphicsView.setBackgroundBrush(brush)
79
-
80
- self.verticalLayout.addWidget(self.graphicsView)
81
-
82
- self.answersLabel = QLabel(QuestionPrevDialog)
83
- self.answersLabel.setObjectName(u"answersLabel")
84
-
85
- self.verticalLayout.addWidget(self.answersLabel)
86
-
87
- self.answersFormLayout = QFormLayout()
88
- self.answersFormLayout.setObjectName(u"answersFormLayout")
89
- self.answersFormLayout.setContentsMargins(-1, 3, -1, -1)
90
-
91
- self.verticalLayout.addLayout(self.answersFormLayout)
92
-
93
- self.buttonBox = QDialogButtonBox(QuestionPrevDialog)
94
- self.buttonBox.setObjectName(u"buttonBox")
95
- self.buttonBox.setOrientation(Qt.Orientation.Horizontal)
96
- self.buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Close)
97
-
98
- self.verticalLayout.addWidget(self.buttonBox)
99
-
100
-
101
- self.retranslateUi(QuestionPrevDialog)
102
- self.buttonBox.accepted.connect(QuestionPrevDialog.accept)
103
- self.buttonBox.rejected.connect(QuestionPrevDialog.reject)
104
-
105
- QMetaObject.connectSlotsByName(QuestionPrevDialog)
106
- # setupUi
107
-
108
- def retranslateUi(self, QuestionPrevDialog):
109
- QuestionPrevDialog.setWindowTitle(QCoreApplication.translate("QuestionPrevDialog", u"Dialog", None))
110
- self.questionNameLabel.setText(QCoreApplication.translate("QuestionPrevDialog", u"Question Name", None))
111
- self.label.setText(QCoreApplication.translate("QuestionPrevDialog", u"Question Type", None))
112
- self.questionText.setText(QCoreApplication.translate("QuestionPrevDialog", u"QuestionText", None))
113
- self.answersLabel.setText(QCoreApplication.translate("QuestionPrevDialog", u"Answers", None))
114
- # retranslateUi
115
-
@@ -1,37 +0,0 @@
1
- excel2moodle/__init__.py,sha256=qdQJY0xbSiEhnmqbgJpqBe0kHec7yLOeAdcArScioE8,1925
2
- excel2moodle/__main__.py,sha256=xnTzJuQL5uDWiwDGoU9vKY4hMSFZIaz0meognglUwxw,1189
3
- excel2moodle/logger.py,sha256=e3i6ECB8x-qyR4mP5WhdDGs1WbFXma2tzBjKbMumfOw,3086
4
- excel2moodle/core/__init__.py,sha256=H4Bt6u076RKb6BH5F58nHLQvYPDUoayosM_Onyr9yT0,398
5
- excel2moodle/core/category.py,sha256=QIl8nh1ryvlVMtNy8hWRfhZZMgGOhQZ3rwDFqf4woa4,1809
6
- excel2moodle/core/dataStructure.py,sha256=xEb24WHMSTXnR5JtpLeacfYyBkP418znQXYBTaUix6k,13209
7
- excel2moodle/core/etHelpers.py,sha256=i8DAx7YBxrQqzbXFsU-pIvYMPHSRhYci-JvuzY1MzeI,2299
8
- excel2moodle/core/exceptions.py,sha256=VgbxrnoR9RRnmDYK2rbB_Bv00r7NLWET6FgddPwo3uw,748
9
- excel2moodle/core/globals.py,sha256=Dg46AveftuGTGpxaFdxF87Kc1Azf0dIFQy8dAdgy0cE,3293
10
- excel2moodle/core/numericMultiQ.py,sha256=vr-gYogu2sf2a_Bhvhnu1ZSZFZXM32MfhJesjTkoOQM,2618
11
- excel2moodle/core/parser.py,sha256=biXKznQdrK0_UNBB4TsV54RqTpAmEnGwZJVC5_wneA0,8549
12
- excel2moodle/core/question.py,sha256=mr0T8qc7C-m-A8_A59JeCyu80SmruRB-iTV5JEAHjAk,8599
13
- excel2moodle/core/settings.py,sha256=6Do6A1VWlVMJYgT0Je4YyFsIS8rEMcghu-MUXBGk1b0,6842
14
- excel2moodle/core/stringHelpers.py,sha256=OzFZ6Eu3PeBLKb61K-aeVfUZmVuBerr9KfyOsuNRd7Y,2403
15
- excel2moodle/core/validator.py,sha256=4U0HEJREtZ7d6K7b4F1NA7P_AC3_uv6Th_1YGLKJwgU,4969
16
- excel2moodle/extra/__init__.py,sha256=PM-id60HD21A3IcGC_fCYFihS8osBGZMIJCcN-ZRsIM,293
17
- excel2moodle/extra/equationVerification.py,sha256=GLJl1r90d8AAiNy0H2hooZrg3D6aEwNfifYKAe3aGxM,3921
18
- excel2moodle/question_types/__init__.py,sha256=ZYGg_tYop9c5yUfN8St6FddeaDxbyE2hneKKUFVzcGM,955
19
- excel2moodle/question_types/mc.py,sha256=DEloENXMME7zpHgUIdQlH_HKMyPbWdNs45r05nseQ8c,4804
20
- excel2moodle/question_types/nf.py,sha256=QcLIGFLTOyZyTouOTbSb9oaqXZAo1wYJz-Ek9oqEVHc,773
21
- excel2moodle/question_types/nfm.py,sha256=ndwZdsCb71MrdPGaftqWxD7IuWFNXKRIN7Qcxe1qTHM,3231
22
- excel2moodle/ui/__init__.py,sha256=4EdGtpzwH3rgw4xW9E5x9kdPQYwKbo9rehHRZTNxCrQ,44
23
- excel2moodle/ui/appUi.py,sha256=3uYIuuLJlUhud5yHo8Uiya3ZOlMUlyWVMtFxHU3ZATk,11284
24
- excel2moodle/ui/dialogs.py,sha256=Xvhkvp4U-0yN5dWK9BaP6j3LzeNLd3YMiA1JvtyCZyw,5636
25
- excel2moodle/ui/exportSettingsDialog.py,sha256=_BldaX74LsaAfy4rG6g7f55tra3OQETnfyRQ-wClvHU,3610
26
- excel2moodle/ui/questionPreviewDialog.py,sha256=_rJvz1GM90aNnj3P6SugEezK7JW6m74ZALgkChohWLM,4980
27
- excel2moodle/ui/treewidget.py,sha256=mTRqmZHMZT3QTTvt5Gw9L-yl4KdhhulkF7O1KBwW-_E,2449
28
- excel2moodle/ui/variantDialog.py,sha256=snVaF3_YAc7NWjMRg7NzbjL_PzNbOpt4eiqElkE46io,5414
29
- excel2moodle/ui/windowDoc.py,sha256=WvzHj6F4JvHP82WlTsyFeOXW024Xq3BUqtp--T4twuI,661
30
- excel2moodle/ui/windowEquationChecker.py,sha256=fLyal3sbJwpthWCAxLB5vbSFOX23JoivoYksNp3mZVY,7925
31
- excel2moodle/ui/windowMain.py,sha256=iHEq9HRRGduPIxV4QOYUkGgKkbmphJT1vKHsrokQbsM,19668
32
- excel2moodle-0.4.1.dist-info/licenses/LICENSE,sha256=ywQqe6Sitymkf2lV2NRcx_aGsaC-KbSl_EfEsRXmNRw,35135
33
- excel2moodle-0.4.1.dist-info/METADATA,sha256=wupC5jQBXubRzjlpK2YPXtJeI1Ng31xjG8lUF-khbZE,2972
34
- excel2moodle-0.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
- excel2moodle-0.4.1.dist-info/entry_points.txt,sha256=r6Dy9TGktIJUdr1QpKni_ANneugiuEtLYUbsKVMn96w,117
36
- excel2moodle-0.4.1.dist-info/top_level.txt,sha256=5V1xRUQ9o7UmOCmNoWCZPAuy5nXp3Qbzyqch8fUGT_c,13
37
- excel2moodle-0.4.1.dist-info/RECORD,,