excel2moodle 0.3.3__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 +64 -55
- excel2moodle/__main__.py +5 -5
- excel2moodle/core/category.py +53 -33
- excel2moodle/core/dataStructure.py +82 -50
- 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 +171 -109
- excel2moodle/core/question.py +86 -57
- excel2moodle/core/questionValidator.py +34 -41
- excel2moodle/core/stringHelpers.py +35 -24
- excel2moodle/extra/__init__.py +1 -3
- excel2moodle/extra/equationVerification.py +40 -22
- excel2moodle/ui/appUi.py +91 -68
- excel2moodle/ui/dialogs.py +35 -18
- excel2moodle/ui/settings.py +44 -7
- {excel2moodle-0.3.3.dist-info → excel2moodle-0.3.4.dist-info}/METADATA +4 -3
- excel2moodle-0.3.4.dist-info/RECORD +32 -0
- {excel2moodle-0.3.3.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.3.dist-info/RECORD +0 -31
- {excel2moodle-0.3.3.dist-info → excel2moodle-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {excel2moodle-0.3.3.dist-info → excel2moodle-0.3.4.dist-info}/top_level.txt +0 -0
excel2moodle/ui/appUi.py
CHANGED
@@ -4,46 +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 .
|
14
|
-
|
9
|
+
|
10
|
+
from PySide6 import QtCore, QtWidgets
|
11
|
+
from PySide6.QtCore import Qt
|
12
|
+
|
13
|
+
from excel2moodle import e2mMetadata, qSignalLogger
|
15
14
|
from excel2moodle.core.dataStructure import QuestionDB
|
16
|
-
from excel2moodle.ui.treewidget import QuestionItem, CategoryItem
|
17
15
|
from excel2moodle.extra import equationVerification as eqVerif
|
18
|
-
from excel2moodle import
|
16
|
+
from excel2moodle.ui import dialogs, windowEquationChecker
|
19
17
|
from excel2moodle.ui.settings import Settings
|
20
|
-
import
|
18
|
+
from excel2moodle.ui.treewidget import CategoryItem, QuestionItem
|
19
|
+
from excel2moodle.ui.windowMain import Ui_MoodleTestGenerator
|
21
20
|
|
21
|
+
from .windowEquationChecker import Ui_EquationChecker
|
22
22
|
|
23
23
|
logger = logging.getLogger(__name__)
|
24
24
|
|
25
25
|
|
26
|
-
|
27
26
|
class MainWindow(QtWidgets.QMainWindow):
|
28
|
-
def __init__(self, settings:Settings, testDB:QuestionDB)->None:
|
27
|
+
def __init__(self, settings: Settings, testDB: QuestionDB) -> None:
|
29
28
|
super().__init__()
|
30
29
|
self.settings = settings
|
31
|
-
self.excelPath: Path|None = None
|
32
|
-
self.mainPath =
|
30
|
+
self.excelPath: Path | None = None
|
31
|
+
self.mainPath = self.excelPath.parent if self.excelPath is not None else None
|
33
32
|
self.exportFile = Path()
|
34
33
|
self.testDB = testDB
|
35
34
|
self.ui = Ui_MoodleTestGenerator()
|
36
35
|
self.ui.setupUi(self)
|
37
36
|
|
38
37
|
self.ui.treeWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
|
39
|
-
self.ui.treeWidget.header().setSectionResizeMode(
|
40
|
-
|
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
|
+
)
|
41
44
|
|
42
45
|
self.ui.retranslateUi(self)
|
43
46
|
logger.info(f"Settings are stored under: {self.settings.fileName()}")
|
44
47
|
self.ui.pointCounter.setReadOnly(True)
|
45
48
|
self.ui.questionCounter.setReadOnly(True)
|
46
|
-
self.setStatus(
|
49
|
+
self.setStatus(
|
50
|
+
"Wählen Sie bitte eine Excel Tabelle und einen Export Ordner für die Fragen aus"
|
51
|
+
)
|
47
52
|
try:
|
48
53
|
self.resize(self.settings.value("windowSize"))
|
49
54
|
self.move(self.settings.value("windowPosition"))
|
@@ -51,14 +56,18 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
51
56
|
pass
|
52
57
|
self.connectEvents()
|
53
58
|
|
54
|
-
def connectEvents(self)->None:
|
59
|
+
def connectEvents(self) -> None:
|
55
60
|
self.ui.treeWidget.itemClicked.connect(self.onSelectionChanged)
|
56
|
-
self.ui.checkBoxQuestionListSelectAll.checkStateChanged.connect(
|
61
|
+
self.ui.checkBoxQuestionListSelectAll.checkStateChanged.connect(
|
62
|
+
self.toggleQuestionSelectionState
|
63
|
+
)
|
57
64
|
qSignalLogger.emitter.signal.connect(self.updateLog)
|
58
65
|
self.ui.actionEquationChecker.triggered.connect(self.onButOpenEqChecker)
|
59
|
-
self.ui.checkBoxIncludeCategories.checkStateChanged.connect(
|
66
|
+
self.ui.checkBoxIncludeCategories.checkStateChanged.connect(
|
67
|
+
self.setIncludeCategoriesSetting
|
68
|
+
)
|
60
69
|
# self.ui.buttonRefresh.clicked.connect(self.refreshList)
|
61
|
-
self.ui.actionParseAll.triggered.connect(self.onParseAll
|
70
|
+
self.ui.actionParseAll.triggered.connect(self.onParseAll)
|
62
71
|
self.testDB.dataChanged.signal.connect(self.onParseAll)
|
63
72
|
self.ui.buttonSpreadSheet.clicked.connect(self.onButSpreadsheet)
|
64
73
|
self.ui.buttonTestGen.clicked.connect(self.onButGenTest)
|
@@ -66,26 +75,24 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
66
75
|
self.ui.actionAbout.triggered.connect(self.onAbout)
|
67
76
|
self.settings.shPathChanged.connect(self.onSheetPathChanged)
|
68
77
|
|
69
|
-
|
70
78
|
@QtCore.Slot(Path)
|
71
|
-
def onSheetPathChanged(self, sheet:Path)->None:
|
79
|
+
def onSheetPathChanged(self, sheet: Path) -> None:
|
72
80
|
logger.debug("Slot, new Spreadsheet triggered")
|
73
81
|
self.spreadSheetPath = sheet
|
74
82
|
self.mainPath = sheet.parent
|
75
83
|
self.ui.buttonSpreadSheet.setText(str(sheet.name))
|
76
84
|
|
77
|
-
def updateLog(self,log)->None:
|
85
|
+
def updateLog(self, log) -> None:
|
78
86
|
self.ui.loggerWindow.append(log)
|
79
87
|
|
80
88
|
def setIncludeCategoriesSetting(self):
|
81
89
|
if self.ui.checkBoxIncludeCategories.isChecked():
|
82
|
-
self.settings.
|
90
|
+
self.settings.testgenSet("includeCats", True)
|
83
91
|
logger.debug("set includeCats to True")
|
84
92
|
else:
|
85
|
-
self.settings.
|
93
|
+
self.settings.testgenSet("includeCats", False)
|
86
94
|
logger.debug("set includeCats to False")
|
87
95
|
|
88
|
-
|
89
96
|
@QtCore.Slot()
|
90
97
|
def onAbout(self):
|
91
98
|
aboutMessage: str = f"""
|
@@ -94,27 +101,27 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
94
101
|
|
95
102
|
<b><a href="{e2mMetadata['homepage']}">{e2mMetadata['name']}</a> - {e2mMetadata['description']}</b>
|
96
103
|
</p>
|
97
|
-
<p style="text-align:center">
|
98
|
-
The documentation can be found under <b
|
99
|
-
</
|
100
|
-
</br>
|
101
|
-
If you encounter any issues please report them under the <a href="{e2mMetadata['issues']}"> repositories issues page</a>
|
104
|
+
<p style="text-align:center">
|
105
|
+
The documentation can be found under <b>
|
106
|
+
<a href="{e2mMetadata['documentation']}">{e2mMetadata['documentation']}</a></b>
|
102
107
|
</br>
|
103
108
|
</p>
|
104
109
|
<p style="text-align:center">
|
105
110
|
This project is maintained by {e2mMetadata['author']}.
|
106
111
|
<br>
|
107
|
-
Development takes place at <a href="{e2mMetadata['homepage']}">{e2mMetadata['homepage']}</a>
|
108
|
-
|
109
|
-
|
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>
|
110
117
|
</p>
|
111
118
|
<p style="text-align:center">
|
112
119
|
<i>This project is published under {e2mMetadata['license']}, you are welcome, to share, modify and reuse the code.</i>
|
113
120
|
</p>
|
114
121
|
"""
|
115
|
-
QtWidgets.QMessageBox.information(
|
116
|
-
|
117
|
-
|
122
|
+
QtWidgets.QMessageBox.information(
|
123
|
+
self, f"About {e2mMetadata['name']}", aboutMessage
|
124
|
+
)
|
118
125
|
|
119
126
|
def closeEvent(self, event):
|
120
127
|
self.settings.setValue("windowSize", self.size())
|
@@ -131,7 +138,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
131
138
|
questions += 1
|
132
139
|
count += q.getQuestion().points
|
133
140
|
|
134
|
-
logger.info(f
|
141
|
+
logger.info(f"{questions} questions are selected with {count} points")
|
135
142
|
self.ui.pointCounter.setValue(count)
|
136
143
|
self.ui.questionCounter.setValue(questions)
|
137
144
|
return None
|
@@ -140,7 +147,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
140
147
|
def toggleQuestionSelectionState(self, state):
|
141
148
|
if state == Qt.Checked:
|
142
149
|
setter = True
|
143
|
-
else:
|
150
|
+
else:
|
151
|
+
setter = False
|
144
152
|
root = self.ui.treeWidget.invisibleRootItem()
|
145
153
|
childN = root.childCount()
|
146
154
|
for i in range(childN):
|
@@ -149,32 +157,37 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
149
157
|
root.child(i).child(q).setSelected(setter)
|
150
158
|
|
151
159
|
@QtCore.Slot()
|
152
|
-
def onButGenTest(self)->None:
|
153
|
-
path = QtWidgets.QFileDialog.getSaveFileName(
|
154
|
-
|
155
|
-
|
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
|
+
)
|
156
168
|
self.exportFile = Path(path[0])
|
157
169
|
logger.info(f"New Export File is set{self.exportFile=}")
|
158
|
-
selection:list[QuestionItem] = self.ui.treeWidget.selectedItems()
|
170
|
+
selection: list[QuestionItem] = self.ui.treeWidget.selectedItems()
|
159
171
|
self.testDB.appendQuestions(selection, self.exportFile)
|
160
172
|
return None
|
161
173
|
|
162
174
|
@QtCore.Slot()
|
163
175
|
def onButSpreadsheet(self):
|
164
|
-
file = QtWidgets.QFileDialog.getOpenFileName(
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
+
)
|
169
183
|
self.excelPath = Path(file[0]).resolve()
|
170
184
|
self.settings.setSpreadsheet(self.excelPath)
|
171
|
-
logger.debug(f
|
185
|
+
logger.debug(f"Saved Spreadsheet Path: {self.excelPath}\n")
|
172
186
|
self.setStatus("[OK] Excel Tabelle wurde eingelesen")
|
173
187
|
return None
|
174
188
|
|
175
|
-
|
176
189
|
@QtCore.Slot()
|
177
|
-
def onParseAll
|
190
|
+
def onParseAll(self) -> None:
|
178
191
|
"""Event triggered by the *Tools/Parse all Questions* Event
|
179
192
|
|
180
193
|
It parses all the Questions found in the spreadsheet and then refreshes the list of questions.
|
@@ -185,23 +198,24 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
185
198
|
self.setStatus("[OK] Alle Fragen wurden erfolgreich in XML-Dateien umgewandelt")
|
186
199
|
# below is former refres method
|
187
200
|
logger.info("starting List refresh")
|
188
|
-
cats =
|
201
|
+
cats = self.testDB.categories
|
189
202
|
self.ui.treeWidget.clear()
|
190
203
|
for cat in cats.values():
|
191
|
-
catItem = CategoryItem(self.ui.treeWidget,cat)
|
204
|
+
catItem = CategoryItem(self.ui.treeWidget, cat)
|
192
205
|
catItem.setFlags(catItem.flags() & ~Qt.ItemIsSelectable)
|
193
206
|
for q in cat.questions.values():
|
194
|
-
QuestionItem(catItem,q)
|
207
|
+
QuestionItem(catItem, q)
|
195
208
|
self.setStatus("[OK] Fragen Liste wurde aktualisiert")
|
196
209
|
return None
|
197
210
|
|
198
211
|
@QtCore.Slot()
|
199
|
-
def previewQ(self)->None:
|
212
|
+
def previewQ(self) -> None:
|
200
213
|
item = self.ui.treeWidget.currentItem()
|
201
214
|
if isinstance(item, QuestionItem):
|
202
215
|
dialog = dialogs.QuestinoPreviewDialog(self, item.getQuestion())
|
203
216
|
dialog.show()
|
204
|
-
else:
|
217
|
+
else:
|
218
|
+
logger.info(f"current Item is not a Question, can't preview")
|
205
219
|
|
206
220
|
def setStatus(self, status):
|
207
221
|
self.ui.statusbar.clearMessage()
|
@@ -221,26 +235,35 @@ class EqCheckerWindow(QtWidgets.QWidget):
|
|
221
235
|
self.excelFile = Path()
|
222
236
|
self.ui = Ui_EquationChecker()
|
223
237
|
self.ui.setupUi(self)
|
224
|
-
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
|
+
)
|
225
243
|
|
226
|
-
def onButRunCheck(self, catN:int, qN:int)->None:
|
244
|
+
def onButRunCheck(self, catN: int, qN: int) -> None:
|
227
245
|
"""
|
228
246
|
Is Triggered by the ``Run Check now`` Button and runs the Equation Check
|
229
247
|
"""
|
230
|
-
|
248
|
+
|
231
249
|
self.ui.textResultsOutput.clear()
|
232
|
-
bullets, results, firstResult = eqVerif.equationChecker(
|
250
|
+
bullets, results, firstResult = eqVerif.equationChecker(
|
251
|
+
f"KAT_{catN}", qN, self.excelFile
|
252
|
+
)
|
233
253
|
check = False
|
234
|
-
self.ui.lineFirstResult.setText(f
|
254
|
+
self.ui.lineFirstResult.setText(f"{firstResult}")
|
235
255
|
for i, calculation in enumerate(results):
|
236
|
-
if i == 0 and firstResult !=0:
|
256
|
+
if i == 0 and firstResult != 0:
|
237
257
|
check = eqVerif.checkResult(firstResult, calculation)
|
238
|
-
self.ui.lineCalculatedRes.setText(f
|
239
|
-
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
|
+
)
|
240
262
|
|
241
263
|
if check == True:
|
242
264
|
self.ui.lineCheckResult.setText("[OK]")
|
243
|
-
logger.info(
|
265
|
+
logger.info(
|
266
|
+
f"Das erste berechnete Ergebnis stimmt mit dem Wert in 'firstResult' überein\n"
|
267
|
+
)
|
244
268
|
else:
|
245
269
|
self.ui.lineCheckResult.setText("[ERROR]")
|
246
|
-
|
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
73
|
for text in self.question.qtextParagraphs:
|
69
|
-
t.append(ET.tostring(text, encoding=
|
70
|
-
|
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,8 +1,11 @@
|
|
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
11
|
if self.contains("core/spreadsheet"):
|
@@ -10,26 +13,60 @@ class Settings(QSettings):
|
|
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()
|
20
|
+
|
21
|
+
def ensureSettings(self) -> None:
|
22
|
+
"""Makes sure all necessary settings are made
|
16
23
|
|
17
|
-
|
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
39
|
return self.value(value, default)
|
24
40
|
|
25
|
-
|
26
41
|
def set(self, setting, value):
|
27
42
|
self.setValue(setting, value)
|
28
43
|
|
29
|
-
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:
|
30
68
|
if isinstance(sheet, Path):
|
31
69
|
self.sheet = sheet.resolve(strict=True)
|
32
70
|
self.setValue("core/spreadsheet", self.sheet)
|
33
71
|
self.shPathChanged.emit(sheet)
|
34
72
|
return None
|
35
|
-
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: excel2moodle
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.4
|
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
|
@@ -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=dsK3KrorPt06FUp18_dw2m4p9P8E7rFf9I0BR-4I28k,4263
|
2
|
-
excel2moodle/__main__.py,sha256=SsulFcOSlRBF2tLTUIdFgB0EJdSLGBIQ_HO53S4Sih8,541
|
3
|
-
excel2moodle/core/__init__.py,sha256=E7smxf7ESHlucvho4Gb5oaTHA7IsOv9J-UDIsoKwp84,399
|
4
|
-
excel2moodle/core/category.py,sha256=rZsQW5-Ud182xCrS4R8B0vrPMrI-azwtfzlTdy89SR4,2982
|
5
|
-
excel2moodle/core/dataStructure.py,sha256=h82r4wO2PhhHA4EqROjfkqWGUpg6UKQhkyrdjdisLxg,6343
|
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=0bLP_bkTFu3URw08sn1zJCvA3YCKxDAC4a6I14koHho,13408
|
11
|
-
excel2moodle/core/question.py,sha256=zzdL_7BdWs0wUVl8-06gLkKu0Is3n0zU-2ZkaYhU504,5913
|
12
|
-
excel2moodle/core/questionValidator.py,sha256=taOrrR6pd5mN7SGpET9eLOvb1v5NWvg_VgMj8opQlZ4,4791
|
13
|
-
excel2moodle/core/questionWriter.py,sha256=kyUTrnjWrLEWdez5_7FPNJ0Cs_fF5d16oOQiVvHv3zA,10242
|
14
|
-
excel2moodle/core/stringHelpers.py,sha256=9BqR7yx2bL8WknVMPuNlmWz05bgi4qWjFYHsgaftpZw,3141
|
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=TEqslEDExDOyYwCh7czg3YZggPdZewFiImbpzACLYLU,10533
|
19
|
-
excel2moodle/ui/dialogs.py,sha256=5dnzRN9cwaxjJsxA7I9v1imH4k6XVzzievYi3PR32XI,3038
|
20
|
-
excel2moodle/ui/questionPreviewDialog.py,sha256=_rJvz1GM90aNnj3P6SugEezK7JW6m74ZALgkChohWLM,4980
|
21
|
-
excel2moodle/ui/settings.py,sha256=PB0uBMCd8DIRSFfvUAPs5hK4UEcb0y7dG9ZJ--kOvuQ,1115
|
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.3.dist-info/licenses/LICENSE,sha256=ywQqe6Sitymkf2lV2NRcx_aGsaC-KbSl_EfEsRXmNRw,35135
|
28
|
-
excel2moodle-0.3.3.dist-info/METADATA,sha256=i7lC9k3j8ErKfWNnPAngdrnDAWIqC5V6egSB5uWivW8,2904
|
29
|
-
excel2moodle-0.3.3.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
30
|
-
excel2moodle-0.3.3.dist-info/top_level.txt,sha256=5V1xRUQ9o7UmOCmNoWCZPAuy5nXp3Qbzyqch8fUGT_c,13
|
31
|
-
excel2moodle-0.3.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|