excel2moodle 0.3.2__py3-none-any.whl → 0.3.4__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.
- excel2moodle/__init__.py +72 -49
- excel2moodle/__main__.py +5 -15
- excel2moodle/core/category.py +53 -62
- excel2moodle/core/dataStructure.py +87 -52
- excel2moodle/core/etHelpers.py +21 -16
- excel2moodle/core/exceptions.py +11 -4
- excel2moodle/core/globals.py +41 -28
- excel2moodle/core/numericMultiQ.py +18 -13
- excel2moodle/core/parser.py +202 -149
- excel2moodle/core/question.py +120 -51
- excel2moodle/core/questionValidator.py +48 -37
- excel2moodle/core/stringHelpers.py +41 -23
- excel2moodle/extra/__init__.py +1 -3
- excel2moodle/extra/equationVerification.py +40 -22
- excel2moodle/ui/appUi.py +113 -69
- excel2moodle/ui/dialogs.py +36 -19
- excel2moodle/ui/settings.py +48 -10
- {excel2moodle-0.3.2.dist-info → excel2moodle-0.3.4.dist-info}/METADATA +7 -6
- excel2moodle-0.3.4.dist-info/RECORD +32 -0
- {excel2moodle-0.3.2.dist-info → excel2moodle-0.3.4.dist-info}/WHEEL +1 -1
- excel2moodle-0.3.4.dist-info/entry_points.txt +2 -0
- excel2moodle-0.3.2.dist-info/RECORD +0 -31
- {excel2moodle-0.3.2.dist-info → excel2moodle-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {excel2moodle-0.3.2.dist-info → excel2moodle-0.3.4.dist-info}/top_level.txt +0 -0
excel2moodle/ui/appUi.py
CHANGED
@@ -4,51 +4,51 @@ It needs to be seperated from ``windowMain.py`` because that file will be change
|
|
4
4
|
which generates the python code from the ``.ui`` file
|
5
5
|
"""
|
6
6
|
|
7
|
-
|
8
|
-
from PySide6.QtCore import Qt
|
9
|
-
from PySide6 import QtWidgets
|
7
|
+
import logging as logging
|
10
8
|
from pathlib import Path
|
11
|
-
|
12
|
-
from
|
13
|
-
from
|
9
|
+
|
10
|
+
from PySide6 import QtCore, QtWidgets
|
11
|
+
from PySide6.QtCore import Qt
|
12
|
+
|
13
|
+
from excel2moodle import e2mMetadata, qSignalLogger
|
14
14
|
from excel2moodle.core.dataStructure import QuestionDB
|
15
|
-
from excel2moodle.ui.treewidget import QuestionItem, CategoryItem
|
16
15
|
from excel2moodle.extra import equationVerification as eqVerif
|
17
|
-
from excel2moodle import
|
16
|
+
from excel2moodle.ui import dialogs, windowEquationChecker
|
18
17
|
from excel2moodle.ui.settings import Settings
|
19
|
-
from excel2moodle.ui.
|
20
|
-
|
21
|
-
|
22
|
-
from excel2moodle import dirDocumentation
|
18
|
+
from excel2moodle.ui.treewidget import CategoryItem, QuestionItem
|
19
|
+
from excel2moodle.ui.windowMain import Ui_MoodleTestGenerator
|
23
20
|
|
21
|
+
from .windowEquationChecker import Ui_EquationChecker
|
24
22
|
|
25
23
|
logger = logging.getLogger(__name__)
|
26
24
|
|
27
25
|
|
28
|
-
|
29
26
|
class MainWindow(QtWidgets.QMainWindow):
|
30
|
-
def __init__(self, settings:Settings, testDB:QuestionDB)->None:
|
27
|
+
def __init__(self, settings: Settings, testDB: QuestionDB) -> None:
|
31
28
|
super().__init__()
|
32
|
-
# self.questionGenerator = questionGenerator
|
33
|
-
# self.readSettings()
|
34
29
|
self.settings = settings
|
35
|
-
self.excelPath: Path|None = None
|
36
|
-
if self.excelPath is not None
|
37
|
-
self.ui.buttonSpreadSheet.setText(self.excelPath.name)
|
38
|
-
self.mainPath = (self.excelPath.parent if self.excelPath is not None else None)
|
30
|
+
self.excelPath: Path | None = None
|
31
|
+
self.mainPath = self.excelPath.parent if self.excelPath is not None else None
|
39
32
|
self.exportFile = Path()
|
40
33
|
self.testDB = testDB
|
41
34
|
self.ui = Ui_MoodleTestGenerator()
|
42
35
|
self.ui.setupUi(self)
|
43
36
|
|
44
|
-
# self.ui.buttonRefresh.clicked.connect(lambda: self.refreshList(self.test))
|
45
37
|
self.ui.treeWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
|
46
|
-
self.ui.treeWidget.header().setSectionResizeMode(
|
38
|
+
self.ui.treeWidget.header().setSectionResizeMode(
|
39
|
+
QtWidgets.QHeaderView.ResizeToContents
|
40
|
+
)
|
41
|
+
self.ui.checkBoxIncludeCategories.setChecked(
|
42
|
+
self.settings.value("testGen/includeCats", type=bool)
|
43
|
+
)
|
47
44
|
|
48
45
|
self.ui.retranslateUi(self)
|
49
46
|
logger.info(f"Settings are stored under: {self.settings.fileName()}")
|
50
47
|
self.ui.pointCounter.setReadOnly(True)
|
51
|
-
self.
|
48
|
+
self.ui.questionCounter.setReadOnly(True)
|
49
|
+
self.setStatus(
|
50
|
+
"Wählen Sie bitte eine Excel Tabelle und einen Export Ordner für die Fragen aus"
|
51
|
+
)
|
52
52
|
try:
|
53
53
|
self.resize(self.settings.value("windowSize"))
|
54
54
|
self.move(self.settings.value("windowPosition"))
|
@@ -56,42 +56,72 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
56
56
|
pass
|
57
57
|
self.connectEvents()
|
58
58
|
|
59
|
-
def connectEvents(self)->None:
|
59
|
+
def connectEvents(self) -> None:
|
60
60
|
self.ui.treeWidget.itemClicked.connect(self.onSelectionChanged)
|
61
|
-
self.ui.checkBoxQuestionListSelectAll.checkStateChanged.connect(
|
61
|
+
self.ui.checkBoxQuestionListSelectAll.checkStateChanged.connect(
|
62
|
+
self.toggleQuestionSelectionState
|
63
|
+
)
|
62
64
|
qSignalLogger.emitter.signal.connect(self.updateLog)
|
63
65
|
self.ui.actionEquationChecker.triggered.connect(self.onButOpenEqChecker)
|
64
|
-
self.ui.checkBoxIncludeCategories.checkStateChanged.connect(
|
66
|
+
self.ui.checkBoxIncludeCategories.checkStateChanged.connect(
|
67
|
+
self.setIncludeCategoriesSetting
|
68
|
+
)
|
65
69
|
# self.ui.buttonRefresh.clicked.connect(self.refreshList)
|
66
|
-
self.ui.actionParseAll.triggered.connect(self.onParseAll
|
70
|
+
self.ui.actionParseAll.triggered.connect(self.onParseAll)
|
67
71
|
self.testDB.dataChanged.signal.connect(self.onParseAll)
|
68
72
|
self.ui.buttonSpreadSheet.clicked.connect(self.onButSpreadsheet)
|
69
73
|
self.ui.buttonTestGen.clicked.connect(self.onButGenTest)
|
70
74
|
self.ui.actionPreviewQ.triggered.connect(self.previewQ)
|
71
|
-
self.ui.
|
75
|
+
self.ui.actionAbout.triggered.connect(self.onAbout)
|
72
76
|
self.settings.shPathChanged.connect(self.onSheetPathChanged)
|
73
77
|
|
74
|
-
|
75
78
|
@QtCore.Slot(Path)
|
76
|
-
def onSheetPathChanged(self, sheet:Path)->None:
|
79
|
+
def onSheetPathChanged(self, sheet: Path) -> None:
|
77
80
|
logger.debug("Slot, new Spreadsheet triggered")
|
78
81
|
self.spreadSheetPath = sheet
|
79
82
|
self.mainPath = sheet.parent
|
83
|
+
self.ui.buttonSpreadSheet.setText(str(sheet.name))
|
80
84
|
|
81
|
-
def updateLog(self,log)->None:
|
85
|
+
def updateLog(self, log) -> None:
|
82
86
|
self.ui.loggerWindow.append(log)
|
83
87
|
|
84
88
|
def setIncludeCategoriesSetting(self):
|
85
89
|
if self.ui.checkBoxIncludeCategories.isChecked():
|
86
|
-
self.settings.
|
90
|
+
self.settings.testgenSet("includeCats", True)
|
91
|
+
logger.debug("set includeCats to True")
|
87
92
|
else:
|
88
|
-
self.settings.
|
93
|
+
self.settings.testgenSet("includeCats", False)
|
94
|
+
logger.debug("set includeCats to False")
|
89
95
|
|
90
96
|
@QtCore.Slot()
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
+
)
|
95
125
|
|
96
126
|
def closeEvent(self, event):
|
97
127
|
self.settings.setValue("windowSize", self.size())
|
@@ -108,7 +138,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
108
138
|
questions += 1
|
109
139
|
count += q.getQuestion().points
|
110
140
|
|
111
|
-
logger.info(f
|
141
|
+
logger.info(f"{questions} questions are selected with {count} points")
|
112
142
|
self.ui.pointCounter.setValue(count)
|
113
143
|
self.ui.questionCounter.setValue(questions)
|
114
144
|
return None
|
@@ -117,7 +147,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
117
147
|
def toggleQuestionSelectionState(self, state):
|
118
148
|
if state == Qt.Checked:
|
119
149
|
setter = True
|
120
|
-
else:
|
150
|
+
else:
|
151
|
+
setter = False
|
121
152
|
root = self.ui.treeWidget.invisibleRootItem()
|
122
153
|
childN = root.childCount()
|
123
154
|
for i in range(childN):
|
@@ -126,34 +157,37 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
126
157
|
root.child(i).child(q).setSelected(setter)
|
127
158
|
|
128
159
|
@QtCore.Slot()
|
129
|
-
def onButGenTest(self)->None:
|
130
|
-
path = QtWidgets.QFileDialog.getSaveFileName(
|
131
|
-
|
132
|
-
|
160
|
+
def onButGenTest(self) -> None:
|
161
|
+
path = QtWidgets.QFileDialog.getSaveFileName(
|
162
|
+
self,
|
163
|
+
"Select Output File",
|
164
|
+
dir=f"{
|
165
|
+
self.mainPath/"Testfile.xml"}",
|
166
|
+
filter="xml Files (*.xml)",
|
167
|
+
)
|
133
168
|
self.exportFile = Path(path[0])
|
134
169
|
logger.info(f"New Export File is set{self.exportFile=}")
|
135
|
-
selection:list[QuestionItem] = self.ui.treeWidget.selectedItems()
|
170
|
+
selection: list[QuestionItem] = self.ui.treeWidget.selectedItems()
|
136
171
|
self.testDB.appendQuestions(selection, self.exportFile)
|
137
172
|
return None
|
138
173
|
|
139
174
|
@QtCore.Slot()
|
140
175
|
def onButSpreadsheet(self):
|
141
|
-
file = QtWidgets.QFileDialog.getOpenFileName(
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
176
|
+
file = QtWidgets.QFileDialog.getOpenFileName(
|
177
|
+
self,
|
178
|
+
self.tr("Open Spreadsheet"),
|
179
|
+
dir=str(self.mainPath),
|
180
|
+
filter=self.tr("Spreadsheet(*.xlsx *.ods)"),
|
181
|
+
selectedFilter=("*.ods"),
|
182
|
+
)
|
146
183
|
self.excelPath = Path(file[0]).resolve()
|
147
184
|
self.settings.setSpreadsheet(self.excelPath)
|
148
|
-
|
149
|
-
self.ui.buttonSpreadSheet.setText(self.excelPath.name)
|
150
|
-
logger.debug(f'Saved Spreadsheet Path: {self.excelPath}\n')
|
185
|
+
logger.debug(f"Saved Spreadsheet Path: {self.excelPath}\n")
|
151
186
|
self.setStatus("[OK] Excel Tabelle wurde eingelesen")
|
152
187
|
return None
|
153
188
|
|
154
|
-
|
155
189
|
@QtCore.Slot()
|
156
|
-
def onParseAll
|
190
|
+
def onParseAll(self) -> None:
|
157
191
|
"""Event triggered by the *Tools/Parse all Questions* Event
|
158
192
|
|
159
193
|
It parses all the Questions found in the spreadsheet and then refreshes the list of questions.
|
@@ -164,23 +198,24 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
164
198
|
self.setStatus("[OK] Alle Fragen wurden erfolgreich in XML-Dateien umgewandelt")
|
165
199
|
# below is former refres method
|
166
200
|
logger.info("starting List refresh")
|
167
|
-
cats =
|
201
|
+
cats = self.testDB.categories
|
168
202
|
self.ui.treeWidget.clear()
|
169
203
|
for cat in cats.values():
|
170
|
-
catItem = CategoryItem(self.ui.treeWidget,cat)
|
204
|
+
catItem = CategoryItem(self.ui.treeWidget, cat)
|
171
205
|
catItem.setFlags(catItem.flags() & ~Qt.ItemIsSelectable)
|
172
206
|
for q in cat.questions.values():
|
173
|
-
QuestionItem(catItem,q)
|
207
|
+
QuestionItem(catItem, q)
|
174
208
|
self.setStatus("[OK] Fragen Liste wurde aktualisiert")
|
175
209
|
return None
|
176
210
|
|
177
211
|
@QtCore.Slot()
|
178
|
-
def previewQ(self)->None:
|
212
|
+
def previewQ(self) -> None:
|
179
213
|
item = self.ui.treeWidget.currentItem()
|
180
214
|
if isinstance(item, QuestionItem):
|
181
215
|
dialog = dialogs.QuestinoPreviewDialog(self, item.getQuestion())
|
182
216
|
dialog.show()
|
183
|
-
else:
|
217
|
+
else:
|
218
|
+
logger.info(f"current Item is not a Question, can't preview")
|
184
219
|
|
185
220
|
def setStatus(self, status):
|
186
221
|
self.ui.statusbar.clearMessage()
|
@@ -200,26 +235,35 @@ class EqCheckerWindow(QtWidgets.QWidget):
|
|
200
235
|
self.excelFile = Path()
|
201
236
|
self.ui = Ui_EquationChecker()
|
202
237
|
self.ui.setupUi(self)
|
203
|
-
self.ui.buttonRunCheck.clicked.connect(
|
238
|
+
self.ui.buttonRunCheck.clicked.connect(
|
239
|
+
lambda: self.onButRunCheck(
|
240
|
+
self.ui.catNumber.value(), self.ui.qNumber.value()
|
241
|
+
)
|
242
|
+
)
|
204
243
|
|
205
|
-
def onButRunCheck(self, catN:int, qN:int)->None:
|
244
|
+
def onButRunCheck(self, catN: int, qN: int) -> None:
|
206
245
|
"""
|
207
246
|
Is Triggered by the ``Run Check now`` Button and runs the Equation Check
|
208
247
|
"""
|
209
|
-
|
248
|
+
|
210
249
|
self.ui.textResultsOutput.clear()
|
211
|
-
bullets, results, firstResult = eqVerif.equationChecker(
|
250
|
+
bullets, results, firstResult = eqVerif.equationChecker(
|
251
|
+
f"KAT_{catN}", qN, self.excelFile
|
252
|
+
)
|
212
253
|
check = False
|
213
|
-
self.ui.lineFirstResult.setText(f
|
254
|
+
self.ui.lineFirstResult.setText(f"{firstResult}")
|
214
255
|
for i, calculation in enumerate(results):
|
215
|
-
if i == 0 and firstResult !=0:
|
256
|
+
if i == 0 and firstResult != 0:
|
216
257
|
check = eqVerif.checkResult(firstResult, calculation)
|
217
|
-
self.ui.lineCalculatedRes.setText(f
|
218
|
-
self.ui.textResultsOutput.append(
|
258
|
+
self.ui.lineCalculatedRes.setText(f"{calculation}")
|
259
|
+
self.ui.textResultsOutput.append(
|
260
|
+
f"Ergebnis {i+1}: \t{calculation}\n\tMit den Werten: \n{bullets[i]}\n"
|
261
|
+
)
|
219
262
|
|
220
263
|
if check == True:
|
221
264
|
self.ui.lineCheckResult.setText("[OK]")
|
222
|
-
logger.info(
|
265
|
+
logger.info(
|
266
|
+
f"Das erste berechnete Ergebnis stimmt mit dem Wert in 'firstResult' überein\n"
|
267
|
+
)
|
223
268
|
else:
|
224
269
|
self.ui.lineCheckResult.setText("[ERROR]")
|
225
|
-
|
excel2moodle/ui/dialogs.py
CHANGED
@@ -1,16 +1,17 @@
|
|
1
|
-
"""This Module hosts the various Dialog Classes, that can be shown from main Window
|
2
|
-
|
3
|
-
from PySide6 import QtWidgets, QtGui
|
1
|
+
"""This Module hosts the various Dialog Classes, that can be shown from main Window"""
|
2
|
+
|
4
3
|
import lxml.etree as ET
|
4
|
+
from PySide6 import QtGui, QtWidgets
|
5
5
|
from PySide6.QtSvgWidgets import QGraphicsSvgItem
|
6
6
|
|
7
|
+
from excel2moodle.core.globals import XMLTags
|
7
8
|
from excel2moodle.core.question import Question
|
8
|
-
from excel2moodle.ui.variantDialog import Ui_Dialog
|
9
9
|
from excel2moodle.ui.questionPreviewDialog import Ui_QuestionPrevDialog
|
10
|
+
from excel2moodle.ui.variantDialog import Ui_Dialog
|
10
11
|
|
11
12
|
|
12
13
|
class QuestionVariantDialog(QtWidgets.QDialog):
|
13
|
-
def __init__(self,
|
14
|
+
def __init__(self, parent, question: Question):
|
14
15
|
super().__init__(parent)
|
15
16
|
self.setWindowTitle("Question Variant Dialog")
|
16
17
|
self.maxVal = question.variants
|
@@ -31,7 +32,7 @@ class QuestionVariantDialog(QtWidgets.QDialog):
|
|
31
32
|
|
32
33
|
|
33
34
|
class QuestinoPreviewDialog(QtWidgets.QDialog):
|
34
|
-
def __init__(self, parent: QtWidgets.QWidget, question:Question) -> None:
|
35
|
+
def __init__(self, parent: QtWidgets.QWidget, question: Question) -> None:
|
35
36
|
super().__init__(parent)
|
36
37
|
self.question = question
|
37
38
|
self.ui = Ui_QuestionPrevDialog()
|
@@ -39,42 +40,58 @@ class QuestinoPreviewDialog(QtWidgets.QDialog):
|
|
39
40
|
self.setWindowTitle(f"Question - {question.id} - Preview")
|
40
41
|
self.setupQuestion()
|
41
42
|
|
42
|
-
def setupQuestion(self)->None:
|
43
|
+
def setupQuestion(self) -> None:
|
43
44
|
self.ui.qNameLine.setText(self.question.name)
|
44
45
|
self.ui.qTypeLine.setText(self.question.qtype)
|
45
46
|
self.setText()
|
46
47
|
self.setAnswers()
|
47
48
|
self.setPicture()
|
48
49
|
|
49
|
-
def setPicture(self)->None:
|
50
|
+
def setPicture(self) -> None:
|
50
51
|
if hasattr(self.question, "picture") and self.question.picture.ready:
|
51
52
|
self.picScene = QtWidgets.QGraphicsScene(self)
|
52
53
|
self.ui.graphicsView.setScene(self.picScene)
|
53
54
|
path = self.question.picture.path
|
54
|
-
if path.suffix ==
|
55
|
+
if path.suffix == ".svg":
|
55
56
|
picItem = QGraphicsSvgItem(str(self.question.picture.path))
|
56
57
|
else:
|
57
58
|
pic = QtGui.QPixmap(self.question.picture.path)
|
58
59
|
aspRat = pic.height() // pic.width()
|
59
60
|
width = 400
|
60
61
|
scaleHeight = aspRat * width
|
61
|
-
picItem = QtWidgets.QGraphicsPixmapItem(
|
62
|
+
picItem = QtWidgets.QGraphicsPixmapItem(
|
63
|
+
pic.scaled(
|
64
|
+
width, scaleHeight, QtGui.Qt.AspectRatioMode.KeepAspectRatio
|
65
|
+
)
|
66
|
+
)
|
62
67
|
self.picScene.addItem(picItem)
|
63
68
|
else:
|
64
69
|
self.ui.graphicsView.setFixedHeight(1)
|
65
70
|
|
66
|
-
def setText(self)->None:
|
71
|
+
def setText(self) -> None:
|
67
72
|
t = []
|
68
|
-
for text in self.question.
|
69
|
-
t.append(ET.tostring(text, encoding=
|
70
|
-
|
73
|
+
for text in self.question.qtextParagraphs:
|
74
|
+
t.append(ET.tostring(text, encoding="unicode"))
|
75
|
+
if self.question.bulletList is not None:
|
76
|
+
t.append(ET.tostring(self.question.bulletList, encoding="unicode"))
|
71
77
|
self.ui.questionText.setText("\n".join(t))
|
72
78
|
|
73
|
-
def setAnswers(self)->None:
|
79
|
+
def setAnswers(self) -> None:
|
74
80
|
if self.question.qtype == "NFM":
|
75
|
-
for i,ans in enumerate(self.question.answerVariants):
|
76
|
-
a = ans.find(
|
77
|
-
text = QtWidgets.QLineEdit(a, self
|
78
|
-
self.ui.answersFormLayout.addRow(f
|
81
|
+
for i, ans in enumerate(self.question.answerVariants):
|
82
|
+
a = ans.find("text").text
|
83
|
+
text = QtWidgets.QLineEdit(a, self)
|
84
|
+
self.ui.answersFormLayout.addRow(f"Answer {i+1}", text)
|
79
85
|
|
86
|
+
elif self.question.qtype == "NF":
|
87
|
+
ans = self.question.element.find(XMLTags.ANSWER)
|
88
|
+
a = ans.find("text").text
|
89
|
+
text = QtWidgets.QLineEdit(a, self)
|
90
|
+
self.ui.answersFormLayout.addRow(f"Result", text)
|
80
91
|
|
92
|
+
elif self.question.qtype == "MC":
|
93
|
+
for i, ans in enumerate(self.question.element.findall(XMLTags.ANSWER)):
|
94
|
+
a = ans.find("text").text
|
95
|
+
frac = ans.get("fraction")
|
96
|
+
text = QtWidgets.QLineEdit(a, self)
|
97
|
+
self.ui.answersFormLayout.addRow(f"Fraction: {frac}", text)
|
excel2moodle/ui/settings.py
CHANGED
@@ -1,34 +1,72 @@
|
|
1
|
-
from PySide6.QtCore import QSettings, QTimer, Signal
|
2
1
|
from pathlib import Path
|
3
2
|
|
3
|
+
from PySide6.QtCore import QSettings, QTimer, Signal
|
4
|
+
|
5
|
+
|
4
6
|
class Settings(QSettings):
|
5
7
|
shPathChanged = Signal(Path)
|
8
|
+
|
6
9
|
def __init__(self):
|
7
10
|
super().__init__("jbosse3", "excel2moodle")
|
8
|
-
if self.contains("spreadsheet"):
|
9
|
-
self.sheet = self.value("spreadsheet")
|
11
|
+
if self.contains("core/spreadsheet"):
|
12
|
+
self.sheet = self.value("core/spreadsheet")
|
10
13
|
try:
|
11
14
|
self.sheet.resolve(strict=True)
|
12
15
|
if self.sheet.is_file():
|
13
|
-
QTimer.singleShot(0,self._emitSpreadsheetChanged)
|
16
|
+
QTimer.singleShot(0, self._emitSpreadsheetChanged)
|
14
17
|
except Exception:
|
15
18
|
return None
|
19
|
+
self.ensureSettings()
|
16
20
|
|
17
|
-
def
|
21
|
+
def ensureSettings(self) -> None:
|
22
|
+
"""Makes sure all necessary settings are made
|
23
|
+
|
24
|
+
if not yet inside the settings file, they will be appended
|
25
|
+
"""
|
26
|
+
print("setting necessary settings")
|
27
|
+
|
28
|
+
if not self.contains("parser/nf/tolerance"):
|
29
|
+
self.setValue("parser/nf/tolerance", 1)
|
30
|
+
|
31
|
+
if not self.contains("core/pictureSubFolder"):
|
32
|
+
self.set("core/pictureSubFolder", "Abbildungen_SVG")
|
33
|
+
|
34
|
+
def _emitSpreadsheetChanged(self) -> None:
|
18
35
|
self.shPathChanged.emit(self.sheet)
|
19
36
|
print("Emitting Spreadsheet Changed Event")
|
20
37
|
|
21
|
-
|
22
38
|
def get(self, value, default=None):
|
23
|
-
self.value(value, default)
|
39
|
+
return self.value(value, default)
|
24
40
|
|
25
41
|
def set(self, setting, value):
|
26
42
|
self.setValue(setting, value)
|
27
43
|
|
28
|
-
def
|
44
|
+
def parserSet(self, setting, value) -> None:
|
45
|
+
self.beginGroup("parser")
|
46
|
+
self.setValue(setting, value)
|
47
|
+
self.endGroup()
|
48
|
+
|
49
|
+
def nfParserSet(self, setting, value) -> None:
|
50
|
+
self.beginGroup("parser")
|
51
|
+
self.setValue(setting, value)
|
52
|
+
self.endGroup()
|
53
|
+
|
54
|
+
def parserGet(self, value, default=None, **kwargs):
|
55
|
+
self.beginGroup("parser")
|
56
|
+
return self.value(value, default, **kwargs)
|
57
|
+
|
58
|
+
def testgenSet(self, setting, value) -> None:
|
59
|
+
self.beginGroup("testGen")
|
60
|
+
self.setValue(setting, value)
|
61
|
+
self.endGroup()
|
62
|
+
|
63
|
+
def testgenGet(self, value, default=None):
|
64
|
+
self.beginGroup("testGen")
|
65
|
+
return self.value(value, default)
|
66
|
+
|
67
|
+
def setSpreadsheet(self, sheet: Path) -> None:
|
29
68
|
if isinstance(sheet, Path):
|
30
69
|
self.sheet = sheet.resolve(strict=True)
|
31
|
-
self.setValue("spreadsheet", self.sheet)
|
70
|
+
self.setValue("core/spreadsheet", self.sheet)
|
32
71
|
self.shPathChanged.emit(sheet)
|
33
72
|
return None
|
34
|
-
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: excel2moodle
|
3
|
-
Version: 0.3.
|
4
|
-
Summary: A
|
3
|
+
Version: 0.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
|
7
|
-
Project-URL:
|
8
|
-
Project-URL:
|
7
|
+
Project-URL: Repository, https://gitlab.com/jbosse3/excel2moodle.git
|
8
|
+
Project-URL: Documentation, https://jbosse3.gitlab.io/excel2moodle
|
9
9
|
Keywords: moodle,XML,teaching,question,converter
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
11
11
|
Classifier: Operating System :: OS Independent
|
@@ -15,8 +15,9 @@ License-File: LICENSE
|
|
15
15
|
Requires-Dist: pyside6>=6.8.0
|
16
16
|
Requires-Dist: pandas>=2.1.3
|
17
17
|
Requires-Dist: openpyxl>=3.1.5
|
18
|
-
Requires-Dist:
|
19
|
-
Requires-Dist: odfpy
|
18
|
+
Requires-Dist: lxml>=5.4.0
|
19
|
+
Requires-Dist: odfpy>=1.4.1
|
20
|
+
Requires-Dist: asteval>=1.0.6
|
20
21
|
Dynamic: license-file
|
21
22
|
|
22
23
|
# excel 2 Moodle
|
@@ -0,0 +1,32 @@
|
|
1
|
+
excel2moodle/__init__.py,sha256=LAJas1vxu_JirKDM5b1Jp11SkA7BRei61dk-SrqJg8g,4249
|
2
|
+
excel2moodle/__main__.py,sha256=8o3KK_RDgyTNW05cRL_iiu7BBHbIqWX9H878eHvf9Ag,544
|
3
|
+
excel2moodle/core/__init__.py,sha256=E7smxf7ESHlucvho4Gb5oaTHA7IsOv9J-UDIsoKwp84,399
|
4
|
+
excel2moodle/core/category.py,sha256=p1Njl9QGBdc_5GPCZ7DJbHxNSP-eI0CH7oevkW69jXc,3005
|
5
|
+
excel2moodle/core/dataStructure.py,sha256=xz_tQcLCAXRHEl-8U4fjEQVNKlLyPiH4x_90QXgKLsM,6922
|
6
|
+
excel2moodle/core/etHelpers.py,sha256=3ZYrYomaPax5uXnG4i4aCTeyF9szMbkJVS5-RPabEZQ,2343
|
7
|
+
excel2moodle/core/exceptions.py,sha256=M1iItmJFF1UzCdOBgYseB_fze76UXKWocmxK9_YtDC4,740
|
8
|
+
excel2moodle/core/globals.py,sha256=w_KfucRD8uIffilx0nJCtQSokZEBnxorkge_RPjd3XI,3679
|
9
|
+
excel2moodle/core/numericMultiQ.py,sha256=nuNZugvH6FSU36eyWTqqKz7y6unE34FOGePpZ8K_Iz8,2721
|
10
|
+
excel2moodle/core/parser.py,sha256=oVUBWlRSYI27OtncE_dvTbbAKRUq8VrtKncgNmUMI1Y,14577
|
11
|
+
excel2moodle/core/question.py,sha256=yM8E2bhfkydwGSb6CTEd3lNtFo8ynIzKUGuq7BkMW2s,6306
|
12
|
+
excel2moodle/core/questionValidator.py,sha256=0LqA5VVdlm4OXb753kRD8ADtcVpP5Id4P9DAeelvfLY,4694
|
13
|
+
excel2moodle/core/questionWriter.py,sha256=kyUTrnjWrLEWdez5_7FPNJ0Cs_fF5d16oOQiVvHv3zA,10242
|
14
|
+
excel2moodle/core/stringHelpers.py,sha256=26pqaqtwE10MwKbrN7QcLEfGLJu71aCu0mi0YIigCxY,3251
|
15
|
+
excel2moodle/extra/__init__.py,sha256=PM-id60HD21A3IcGC_fCYFihS8osBGZMIJCcN-ZRsIM,293
|
16
|
+
excel2moodle/extra/equationVerification.py,sha256=pozULgIiTuHUB3fBkgugfJdoaZGMcy6WTrw_wL3sHO4,4398
|
17
|
+
excel2moodle/ui/__init__.py,sha256=4EdGtpzwH3rgw4xW9E5x9kdPQYwKbo9rehHRZTNxCrQ,44
|
18
|
+
excel2moodle/ui/appUi.py,sha256=AE_Kob-ddawVfIWDAJWoymT9dB8hN0kmb-9yGXWMrF8,10519
|
19
|
+
excel2moodle/ui/dialogs.py,sha256=ye17B_jJcLwUCxrgnUDsSekip2lvNFFUAmFWqqizJdM,3821
|
20
|
+
excel2moodle/ui/questionPreviewDialog.py,sha256=_rJvz1GM90aNnj3P6SugEezK7JW6m74ZALgkChohWLM,4980
|
21
|
+
excel2moodle/ui/settings.py,sha256=JOGtjUrM5dKpMjzGR4fCH90yTHgStiBHhrICRGQgssc,2305
|
22
|
+
excel2moodle/ui/treewidget.py,sha256=xiYWhJeJ9o9Iubtr44HcyJas9v4m8aBsHNdokQAHi80,2357
|
23
|
+
excel2moodle/ui/variantDialog.py,sha256=snVaF3_YAc7NWjMRg7NzbjL_PzNbOpt4eiqElkE46io,5414
|
24
|
+
excel2moodle/ui/windowDoc.py,sha256=IciZpwrLnGzIQV1aCdKQBg6km3oufHGs8havTFzNJyU,1055
|
25
|
+
excel2moodle/ui/windowEquationChecker.py,sha256=fLyal3sbJwpthWCAxLB5vbSFOX23JoivoYksNp3mZVY,7925
|
26
|
+
excel2moodle/ui/windowMain.py,sha256=sB1ahkAwxFxO3EYP3X_MuB6ohgXwK5NUQHWeFo4eqrI,21062
|
27
|
+
excel2moodle-0.3.4.dist-info/licenses/LICENSE,sha256=ywQqe6Sitymkf2lV2NRcx_aGsaC-KbSl_EfEsRXmNRw,35135
|
28
|
+
excel2moodle-0.3.4.dist-info/METADATA,sha256=BB871FJP7X3BAUgxKM-7Jk9afnpKb1rVp9b1BBaDEu8,2945
|
29
|
+
excel2moodle-0.3.4.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
30
|
+
excel2moodle-0.3.4.dist-info/entry_points.txt,sha256=myfMLDThuGgWHMJDPPfILiZqo_7D3fhmDdJGqWOAjPw,60
|
31
|
+
excel2moodle-0.3.4.dist-info/top_level.txt,sha256=5V1xRUQ9o7UmOCmNoWCZPAuy5nXp3Qbzyqch8fUGT_c,13
|
32
|
+
excel2moodle-0.3.4.dist-info/RECORD,,
|
@@ -1,31 +0,0 @@
|
|
1
|
-
excel2moodle/__init__.py,sha256=nb37g9Zga4KqTA5r-GFei9_XCunoPESxww9BL8zzMBI,3841
|
2
|
-
excel2moodle/__main__.py,sha256=yLls1C3w070wtrrRl3_HXs5TNaO8l0yRDGtIAcHmeDk,695
|
3
|
-
excel2moodle/core/__init__.py,sha256=E7smxf7ESHlucvho4Gb5oaTHA7IsOv9J-UDIsoKwp84,399
|
4
|
-
excel2moodle/core/category.py,sha256=6U10HgQQVi0BYO28XrsLbYFqr0GbxEN9U2-fPDTM1Ng,4149
|
5
|
-
excel2moodle/core/dataStructure.py,sha256=8cLqGZLhHRscohrstvsYARWvKekGAfdoMV1zWuUpHCA,6200
|
6
|
-
excel2moodle/core/etHelpers.py,sha256=_fd-fGMVNWt1l8FY7xcA2uXOBahxtq8ggYxRYm4SwdA,2354
|
7
|
-
excel2moodle/core/exceptions.py,sha256=3OLVHMCBgETiOxSsirlsCPvlMN5UgEQcMkRDkCfrUs4,675
|
8
|
-
excel2moodle/core/globals.py,sha256=9V9-KBSsHMdsRZWg2wGrvjAd6dc3XZG4pNPnun0AHGE,3595
|
9
|
-
excel2moodle/core/numericMultiQ.py,sha256=InBrn-tsCCYwDb78sGR3FyFxVeN0GfIg63JGtr_tqg4,2751
|
10
|
-
excel2moodle/core/parser.py,sha256=ruSFHKjwpXggaETrtsUBdZK1BENCe2wppmOLdpKrAAs,13455
|
11
|
-
excel2moodle/core/question.py,sha256=4mbzy6ZodvdM5QfBZltR950BmMdXqSBe9V7HBLZMewM,4198
|
12
|
-
excel2moodle/core/questionValidator.py,sha256=6leCAvMFOieiVJtQEYx4iihiaKuuSBlCpBkpqbzKa3M,4139
|
13
|
-
excel2moodle/core/questionWriter.py,sha256=kyUTrnjWrLEWdez5_7FPNJ0Cs_fF5d16oOQiVvHv3zA,10242
|
14
|
-
excel2moodle/core/stringHelpers.py,sha256=c92YYFluZ6-NIM7K1k0SzN_zB82hh3huNZMH0NnlDLg,3009
|
15
|
-
excel2moodle/extra/__init__.py,sha256=e70OmuW3j7N4ErIIHlK4vkmCKcpRbitJCdJvzjego8c,339
|
16
|
-
excel2moodle/extra/equationVerification.py,sha256=FOvVBQZ357fbA5nYkHjvvWWVP3pQpo4RK3H7vru9v3A,4278
|
17
|
-
excel2moodle/ui/__init__.py,sha256=4EdGtpzwH3rgw4xW9E5x9kdPQYwKbo9rehHRZTNxCrQ,44
|
18
|
-
excel2moodle/ui/appUi.py,sha256=gWLJ3vU-KcHAz0HQXrOk2hGi3LD_8SSC5aPVEpayMEA,9518
|
19
|
-
excel2moodle/ui/dialogs.py,sha256=C58PzPLfkzglsRl-x8Y23TC08_JG03JgFCVFfEi_od8,2961
|
20
|
-
excel2moodle/ui/questionPreviewDialog.py,sha256=_rJvz1GM90aNnj3P6SugEezK7JW6m74ZALgkChohWLM,4980
|
21
|
-
excel2moodle/ui/settings.py,sha256=Zz4zxdGC55Ma6pB1HWdPdiAsN0fnqrPfgOFgSkVnKNA,1092
|
22
|
-
excel2moodle/ui/treewidget.py,sha256=xiYWhJeJ9o9Iubtr44HcyJas9v4m8aBsHNdokQAHi80,2357
|
23
|
-
excel2moodle/ui/variantDialog.py,sha256=snVaF3_YAc7NWjMRg7NzbjL_PzNbOpt4eiqElkE46io,5414
|
24
|
-
excel2moodle/ui/windowDoc.py,sha256=IciZpwrLnGzIQV1aCdKQBg6km3oufHGs8havTFzNJyU,1055
|
25
|
-
excel2moodle/ui/windowEquationChecker.py,sha256=fLyal3sbJwpthWCAxLB5vbSFOX23JoivoYksNp3mZVY,7925
|
26
|
-
excel2moodle/ui/windowMain.py,sha256=sB1ahkAwxFxO3EYP3X_MuB6ohgXwK5NUQHWeFo4eqrI,21062
|
27
|
-
excel2moodle-0.3.2.dist-info/licenses/LICENSE,sha256=ywQqe6Sitymkf2lV2NRcx_aGsaC-KbSl_EfEsRXmNRw,35135
|
28
|
-
excel2moodle-0.3.2.dist-info/METADATA,sha256=f_TnbqQEmg8wy6WuvMuYOTd8u_-h5qw4aKADlcvtzsM,2904
|
29
|
-
excel2moodle-0.3.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
30
|
-
excel2moodle-0.3.2.dist-info/top_level.txt,sha256=5V1xRUQ9o7UmOCmNoWCZPAuy5nXp3Qbzyqch8fUGT_c,13
|
31
|
-
excel2moodle-0.3.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|