excel2moodle 0.4.2__py3-none-any.whl → 0.4.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 CHANGED
@@ -48,11 +48,4 @@ if __package__ is not None:
48
48
  }
49
49
 
50
50
 
51
- isMain: bool = False
52
-
53
51
  mainLogger = logging.getLogger(__name__)
54
-
55
-
56
- def isMainState() -> bool:
57
- mainLogger.debug("Returning mainState %s", isMain)
58
- return isMain
@@ -76,7 +76,18 @@ class QuestionDB:
76
76
  self.categoriesMetaData: pd.DataFrame
77
77
  self.categories: dict[str, Category]
78
78
 
79
- def readCategoriesMetadata(self, sheetPath: Path) -> pd.DataFrame:
79
+ @property
80
+ def spreadsheet(self) -> Path:
81
+ return self._spreadsheet
82
+
83
+ @spreadsheet.setter
84
+ def spreadsheet(self, sheet) -> None:
85
+ self.settings.clear()
86
+ self._spreadsheet = sheet
87
+ self.settings.set(Tags.SPREADSHEETPATH, sheet)
88
+ logger.info("saved new spreadsheet %s", sheet)
89
+
90
+ def readCategoriesMetadata(self, sheetPath: Path | None = None) -> pd.DataFrame:
80
91
  """Read the metadata and questions from the spreadsheet.
81
92
 
82
93
  Get the category data from the spreadsheet and stores it in the
@@ -84,6 +95,7 @@ class QuestionDB:
84
95
  Setup the categories and store them in ``self.categories = {}``
85
96
  Pass the question data to the categories.
86
97
  """
98
+ sheetPath = sheetPath if sheetPath else self.spreadsheet
87
99
  logger.info("Start Parsing the Excel Metadata Sheet\n")
88
100
  with Path(sheetPath).open("rb") as f:
89
101
  settingDf = pd.read_excel(
@@ -111,17 +123,29 @@ class QuestionDB:
111
123
  ) -> None:
112
124
  settings = self.harmonizeDFIndex(settings)
113
125
  for tag, value in settings.iterrows():
114
- self.settings.set(tag, value.iloc[0], local=True)
115
- extraModule = self.settings.get(Tags.IMPORTMODULE)
116
- if extraModule:
126
+ value = value.iloc[0]
127
+ if tag == Tags.TOLERANCE:
128
+ tol = value if value < 1 else value / 100
129
+ if tol > 0 and tol < 1:
130
+ self.settings.set(Tags.TOLERANCE, tol)
131
+ else:
132
+ self.settings.set(tag, value)
133
+ if Tags.IMPORTMODULE in settings.index:
117
134
  logger.warning(
118
135
  "Appending: %s to sys.path. All names defined by it will be usable",
119
136
  mainPath,
120
137
  )
121
138
  sys.path.append(str(mainPath))
139
+ imgFolder = self.settings.get(Tags.SPREADSHEETPATH).parent / self.settings.get(
140
+ Tags.PICTURESUBFOLDER
141
+ )
142
+ if Tags.PICTURESUBFOLDER not in settings.index:
143
+ logger.warning("You didn't specify an image Folder. This may cause errors.")
144
+ self.settings.set(Tags.PICTUREFOLDER, imgFolder.resolve())
122
145
 
123
- def initAllCategories(self, sheetPath: Path) -> None:
146
+ def initAllCategories(self, sheetPath: Path | None = None) -> None:
124
147
  """Read all category sheets and initialize all Categories."""
148
+ sheetPath = sheetPath if sheetPath else self.spreadsheet
125
149
  if not hasattr(self, "categoriesMetaData"):
126
150
  logger.error("Can't process the Categories without Metadata")
127
151
  return
@@ -133,14 +157,15 @@ class QuestionDB:
133
157
  for categoryName in excelFile.sheet_names:
134
158
  logger.debug("Starting to read category %s", categoryName)
135
159
  if categoryName in self.categoriesMetaData.index:
136
- self.initCategory(sheetPath, categoryName)
160
+ self.initCategory(categoryName, sheetPath=sheetPath)
137
161
 
138
- def asyncInitAllCategories(self, sheetPath: Path) -> None:
162
+ def asyncInitAllCategories(self, sheetPath: Path | None = None) -> None:
139
163
  """Read all category sheets asynchron and initialize all Categories.
140
164
 
141
165
  It does the same as `initAllCategories` but the parsing of the excelfile
142
166
  is done asynchron via `concurrent.futures.ProcessPoolExecutor`
143
167
  """
168
+ sheetPath = sheetPath if sheetPath else self.spreadsheet
144
169
  if not hasattr(self, "categoriesMetaData"):
145
170
  logger.error("Can't process the Categories without Metadata")
146
171
  return
@@ -171,10 +196,13 @@ class QuestionDB:
171
196
  logger.exception("Error processing sheet %s: %s", categoryName, e)
172
197
  logger.debug("Future exception: %s", future.exception())
173
198
 
174
- def initCategory(self, sheetPath: Path, categoryName: str) -> bool | Category:
199
+ def initCategory(
200
+ self, categoryName: str, sheetPath: Path | None = None
201
+ ) -> bool | Category:
175
202
  """Read `categoryName` from the ``sheetPath`` and initialize the category.
176
203
  Returns the Category and appends it to `self.categories`.
177
204
  """
205
+ sheetPath = sheetPath if sheetPath else self.spreadsheet
178
206
  katDf = pd.read_excel(
179
207
  sheetPath,
180
208
  sheet_name=str(categoryName),
@@ -139,12 +139,12 @@ class Question:
139
139
  def assemble(self, variant=0) -> None:
140
140
  """Assemble the question to the valid xml Tree."""
141
141
  mainText = self._getTextElement()
142
- textParts = self._assembleMainTextParts()
143
142
  self.logger.debug("Starting assembly")
144
- if hasattr(self, "picture") and self.picture.ready:
145
- self._appendPicture(textParts, mainText)
146
- self.logger.debug("inserted MainText to element")
147
143
  self._setAnswerElement(variant=variant)
144
+ textParts = self._assembleMainTextParts()
145
+ if hasattr(self, "picture") and self.picture.ready:
146
+ mainText.append(self.picture.element)
147
+ self.logger.debug("Appended Picture element to text")
148
148
  mainText.append(etHelpers.getCdatTxtElement(textParts))
149
149
 
150
150
  def _assembleMainTextParts(self, variant=0) -> list[ET.Element]:
@@ -152,11 +152,15 @@ class Question:
152
152
 
153
153
  Intended for the cloze question, where the answers parts are part of the text.
154
154
  """
155
+ self.logger.debug("inserting MainText to element")
155
156
  textParts: list[ET.Element] = []
156
157
  textParts.extend(self.qtextParagraphs)
157
158
  bullets = self._getBPoints(variant=variant)
158
159
  if bullets is not None:
159
160
  textParts.append(bullets)
161
+ if hasattr(self, "picture") and self.picture.ready:
162
+ textParts.append(self.picture.htmlTag)
163
+ self.logger.debug("Appended Picture html to text")
160
164
  return textParts
161
165
 
162
166
  def _getTextElement(self) -> ET.Element:
@@ -171,10 +175,6 @@ class Question:
171
175
  msg = "Cant assamble, if element is none"
172
176
  raise QNotParsedException(msg, self.id)
173
177
 
174
- def _appendPicture(self, textParts: list[ET.Element], mainText: ET.Element) -> None:
175
- textParts.append(self.picture.htmlTag)
176
- mainText.append(self.picture.element)
177
-
178
178
  def _getBPoints(self, variant: int = 0) -> ET.Element:
179
179
  if hasattr(self, "bulletList"):
180
180
  return self.bulletList
@@ -5,10 +5,6 @@ from enum import StrEnum
5
5
  from pathlib import Path
6
6
  from typing import ClassVar, Literal, overload
7
7
 
8
- from PySide6.QtCore import QSettings, QTimer, Signal
9
-
10
- import excel2moodle
11
-
12
8
  logger = logging.getLogger(__name__)
13
9
 
14
10
 
@@ -64,7 +60,7 @@ class Tags(StrEnum):
64
60
  """Get type of the keys data."""
65
61
  return self._typ_
66
62
 
67
- QUESTIONVARIANT = "defaultQuestionVariant", int, 0, "testgen"
63
+ QUESTIONVARIANT = "defaultQuestionVariant", int, 1, "testgen"
68
64
  INCLUDEINCATS = "includeCats", bool, False, "testgen"
69
65
  TOLERANCE = "tolerance", float, 0.01, "parser/nf"
70
66
  PICTUREFOLDER = "pictureFolder", Path, None, "core"
@@ -83,7 +79,7 @@ class Tags(StrEnum):
83
79
  NAME = "name", str, None
84
80
  RESULT = "result", float, None
85
81
  EQUATION = "formula", str, None
86
- PICTURE = "picture", str, False
82
+ PICTURE = "picture", str, None
87
83
  NUMBER = "number", int, None
88
84
  ANSTYPE = "answertype", str, None
89
85
  QUESTIONPART = "part", list, None
@@ -93,36 +89,26 @@ class Tags(StrEnum):
93
89
  PICTUREWIDTH = "imgwidth", int, 500
94
90
  ANSPICWIDTH = "answerimgwidth", int, 120
95
91
  WRONGSIGNPERCENT = "wrongsignpercentage", int, 50
96
- FIRSTRESULT = "firstresult", float, None
97
-
92
+ FIRSTRESULT = "firstresult", float, 0
98
93
 
99
- class Settings(QSettings):
100
- """Settings for Excel2moodle."""
101
94
 
102
- shPathChanged = Signal(Path)
103
- localSettings: ClassVar[dict[str, str | float | Path]] = {}
95
+ class Settings:
96
+ values: ClassVar[dict[str, str | float | Path]] = {}
104
97
 
105
- def __init__(self) -> None:
106
- """Instantiate the settings."""
107
- super().__init__("jbosse3", "excel2moodle")
108
- if excel2moodle.isMainState():
109
- logger.info("Settings are stored under: %s", self.fileName())
110
- if self.contains(Tags.SPREADSHEETPATH.full):
111
- self.sheet = self.get(Tags.SPREADSHEETPATH)
112
- if self.sheet.is_file():
113
- QTimer.singleShot(300, self._emitSpreadsheetChanged)
114
-
115
- def _emitSpreadsheetChanged(self) -> None:
116
- self.shPathChanged.emit(self.sheet)
98
+ @classmethod
99
+ def clear(cls) -> None:
100
+ cls.values.clear()
117
101
 
118
102
  @overload
103
+ @classmethod
119
104
  def get(
120
- self,
105
+ cls,
121
106
  key: Literal[Tags.POINTS],
122
107
  ) -> float: ...
123
108
  @overload
109
+ @classmethod
124
110
  def get(
125
- self,
111
+ cls,
126
112
  key: Literal[
127
113
  Tags.QUESTIONVARIANT,
128
114
  Tags.TOLERANCE,
@@ -133,10 +119,12 @@ class Settings(QSettings):
133
119
  ],
134
120
  ) -> int: ...
135
121
  @overload
136
- def get(self, key: Literal[Tags.INCLUDEINCATS]) -> bool: ...
122
+ @classmethod
123
+ def get(cls, key: Literal[Tags.INCLUDEINCATS]) -> bool: ...
137
124
  @overload
125
+ @classmethod
138
126
  def get(
139
- self,
127
+ cls,
140
128
  key: Literal[
141
129
  Tags.PICTURESUBFOLDER,
142
130
  Tags.LOGLEVEL,
@@ -146,26 +134,28 @@ class Settings(QSettings):
146
134
  ],
147
135
  ) -> str: ...
148
136
  @overload
137
+ @classmethod
149
138
  def get(
150
- self,
139
+ cls,
151
140
  key: Literal[Tags.PICTUREFOLDER, Tags.SPREADSHEETPATH],
152
141
  ) -> Path: ...
153
142
 
154
- def get(self, key: Tags):
143
+ @classmethod
144
+ def get(cls, key: Tags):
155
145
  """Get the typesafe settings value.
156
146
 
157
- If local Settings are stored, they are returned.
158
147
  If no setting is made, the default value is returned.
159
148
  """
160
- if key in type(self).localSettings:
161
- val = key.typ()(type(self).localSettings[key])
162
- logger.debug("Returning project setting: %s = %s", key, val)
163
- return val
164
- if not excel2moodle.isMainState():
165
- logger.warning("No GUI: Returning default value.")
166
- return key.default
149
+ try:
150
+ raw = cls.values[key]
151
+ except KeyError:
152
+ default = key.default
153
+ if default is None:
154
+ return None
155
+ logger.info("Returning the default value for %s", key)
156
+ return default
167
157
  if key.typ() is Path:
168
- path: Path = self.value(key.full, defaultValue=key.default)
158
+ path: Path = Path(raw)
169
159
  try:
170
160
  path.resolve(strict=True)
171
161
  except ValueError:
@@ -175,10 +165,7 @@ class Settings(QSettings):
175
165
  return key.default
176
166
  logger.debug("Returning path setting: %s = %s", key, path)
177
167
  return path
178
- raw = self.value(key.full, defaultValue=key.default, type=key.typ())
179
- logger.debug("read a settings Value: %s of type: %s", key, key.typ())
180
168
  try:
181
- logger.debug("Returning global setting: %s = %s", key, raw)
182
169
  return key.typ()(raw)
183
170
  except (ValueError, TypeError):
184
171
  logger.warning(
@@ -186,44 +173,25 @@ class Settings(QSettings):
186
173
  )
187
174
  return key.default
188
175
 
176
+ @classmethod
189
177
  def set(
190
- self,
178
+ cls,
191
179
  key: Tags | str,
192
180
  value: float | bool | Path | str,
193
- local: bool = False,
194
181
  ) -> None:
195
- """Set the setting to value.
196
-
197
- Parameters
198
- ----------
199
- local
200
- True saves local project specific settings.
201
- Defaults to False
202
- The local settings are meant to be set in the first sheet `settings`
203
-
204
- """
205
- if not excel2moodle.isMainState():
206
- local = True
207
- if local:
208
- if key in Tags:
209
- type(self).localSettings[key] = value
210
- logger.info("Saved the project setting %s = %s", key, value)
211
- else:
212
- logger.warning("got invalid local Setting %s = %s", key, value)
213
- return
214
- if not local and isinstance(key, Tags):
215
- if not isinstance(value, key.typ()):
216
- logger.error("trying to save setting with wrong type not possible")
182
+ """Set the setting to value."""
183
+ if key in Tags:
184
+ tag = Tags(key) if not isinstance(key, Tags) else key
185
+ try:
186
+ cls.values[tag] = tag.typ()(value)
187
+ except TypeError:
188
+ logger.exception(
189
+ "trying to save %s = %s %s with wrong type not possible.",
190
+ tag,
191
+ value,
192
+ type(value),
193
+ )
217
194
  return
218
- self.setValue(key.full, value)
219
- logger.info("Saved the global setting %s = %s", key, value)
220
-
221
- def setSpreadsheet(self, sheet: Path) -> None:
222
- """Save spreadsheet path and emit the changed event."""
223
- if isinstance(sheet, Path):
224
- self.sheet = sheet.resolve(strict=True)
225
- logpath = str(self.sheet.parent / "excel2moodleLogFile.log")
226
- self.set(Tags.LOGFILE, logpath)
227
- self.set(Tags.SPREADSHEETPATH, self.sheet)
228
- self.shPathChanged.emit(sheet)
229
- return
195
+ logger.info("Saved %s = %s, type %s", key, value, tag.typ())
196
+ else:
197
+ logger.warning("got invalid local Setting %s = %s", key, value)
@@ -80,9 +80,9 @@ class Validator:
80
80
  if key.startswith(tag) and not isinstance(self.qdata[key], list):
81
81
  self.qdata[key] = stringHelpers.getListFromStr(self.qdata[key])
82
82
  tol = float(self.qdata.get(Tags.TOLERANCE, 0))
83
- if tol <= 0 or tol > 99:
84
- self.qdata[Tags.TOLERANCE] = settings.get(Tags.TOLERANCE)
85
- else:
83
+ if tol < 0 or tol > 99:
84
+ tol = settings.get(Tags.TOLERANCE)
85
+ elif tol != 0:
86
86
  self.qdata[Tags.TOLERANCE] = tol if tol < 1 else tol / 100
87
87
 
88
88
  if self.qdata[Tags.TYPE] == "NFM":
excel2moodle/logger.py CHANGED
@@ -6,10 +6,11 @@ This includes emitting the signals for the main Window, to fast forward all logs
6
6
 
7
7
  import logging
8
8
 
9
- from PySide6.QtCore import QObject, Signal
9
+ from PySide6.QtCore import QObject, QSettings, Signal
10
10
 
11
11
  from excel2moodle.core.settings import Settings, Tags
12
12
 
13
+ qSettings = QSettings("jbosse3", "excel2moodle")
13
14
  settings = Settings()
14
15
 
15
16
  loggerConfig = {
@@ -36,7 +37,9 @@ loggerConfig = {
36
37
  "formatter": "file",
37
38
  "class": "logging.FileHandler",
38
39
  # "class": "logging.handlers.TimedRotatingFileHandler",
39
- "filename": settings.get(Tags.LOGFILE),
40
+ "filename": qSettings.value(
41
+ Tags.LOGFILE, defaultValue=Tags.LOGFILE.default
42
+ ),
40
43
  # "when": "M",
41
44
  # "interval": 1,
42
45
  # "backupCount": "3",
@@ -32,7 +32,7 @@ class ClozeQuestion(ParametricQuestion):
32
32
 
33
33
  def _setAnswerElement(self, variant: int = 1) -> None:
34
34
  for part, ans in self.answerVariants.items():
35
- result = ans[variant]
35
+ result = ans[variant - 1]
36
36
  if self.answerTypes.get(part, None) == "MC":
37
37
  ansStr = ClozeQuestionParser.getMCAnsStr(answers)
38
38
  else:
@@ -45,15 +45,15 @@ class NFMQuestionParser(QuestionParser):
45
45
  super().__init__()
46
46
  self.genFeedbacks = [XMLTags.GENFEEDB]
47
47
  self.question: NFMQuestion
48
-
49
- def setup(self, question: NFMQuestion) -> None:
50
- self.question: NFMQuestion = question
51
- super().setup(question)
52
48
  module = self.settings.get(Tags.IMPORTMODULE)
53
49
  if module and not type(self).astEval.symtable.get(module):
54
50
  type(self).astEval(f"import {module}")
55
51
  self.logger.warning("Imported '%s' to Asteval symtable", module)
56
52
 
53
+ def setup(self, question: NFMQuestion) -> None:
54
+ self.question: NFMQuestion = question
55
+ super().setup(question)
56
+
57
57
  def _parseAnswers(self) -> None:
58
58
  equation = self.rawInput.get(Tags.EQUATION)
59
59
  bps = self.rawInput.get(Tags.BPOINTS)
excel2moodle/ui/appUi.py CHANGED
@@ -8,7 +8,7 @@ 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
@@ -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()
@@ -43,16 +46,16 @@ class MainWindow(QtWidgets.QMainWindow):
43
46
  self.questionPreview = dialogs.QuestionPreview(self)
44
47
  self.eqChecker = EqCheckerWindow()
45
48
  self.connectEvents()
46
- logger.info("Settings are stored under: %s", self.settings.fileName())
49
+ logger.info("Settings are stored under: %s", self.qSettings.fileName())
47
50
  self.ui.treeWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
48
51
  self.ui.treeWidget.header().setSectionResizeMode(
49
52
  QtWidgets.QHeaderView.ResizeToContents,
50
53
  )
51
54
  self.exportDialog.ui.checkBoxIncludeCategories.setChecked(
52
- self.settings.get(Tags.INCLUDEINCATS),
55
+ self.qSettings.value(Tags.INCLUDEINCATS, defaultValue=True, type=bool)
53
56
  )
54
57
  self.exportDialog.ui.spinBoxDefaultQVariant.setValue(
55
- self.settings.get(Tags.QUESTIONVARIANT)
58
+ self.qSettings.value(Tags.QUESTIONVARIANT, defaultValue=1, type=int)
56
59
  )
57
60
  self.ui.pointCounter.setReadOnly(True)
58
61
  self.ui.questionCounter.setReadOnly(True)
@@ -60,11 +63,14 @@ class MainWindow(QtWidgets.QMainWindow):
60
63
  "Wählen Sie eine Excel Tabelle mit den Fragen aus",
61
64
  )
62
65
  try:
63
- self.resize(self.settings.value("windowSize"))
64
- self.move(self.settings.value("windowPosition"))
66
+ self.resize(self.qSettings.value("windowSize"))
67
+ self.move(self.qSettings.value("windowPosition"))
65
68
  except Exception:
66
69
  pass
67
70
  self.threadPool = QThreadPool()
71
+ if self.qSettings.contains(Tags.SPREADSHEETPATH.full):
72
+ sheet = self.qSettings.value(Tags.SPREADSHEETPATH.full)
73
+ self.setSheetPath(sheet)
68
74
 
69
75
  def connectEvents(self) -> None:
70
76
  self.ui.treeWidget.itemSelectionChanged.connect(self.onSelectionChanged)
@@ -85,7 +91,6 @@ class MainWindow(QtWidgets.QMainWindow):
85
91
  self.ui.treeWidget.itemClicked.connect(self.updateQuestionPreview)
86
92
  self.ui.actionAbout.triggered.connect(self.openAboutDlg)
87
93
  self.ui.actionDocumentation.triggered.connect(self.openDocumentation)
88
- self.settings.shPathChanged.connect(self.onSheetPathChanged)
89
94
  self.exportDialog.ui.spinBoxDefaultQVariant.valueChanged.connect(
90
95
  self.setQVariantDefault
91
96
  )
@@ -103,19 +108,23 @@ class MainWindow(QtWidgets.QMainWindow):
103
108
  If successful it prints out a list of all exported Questions
104
109
  """
105
110
  self.ui.treeWidget.clear()
111
+ self.testDB.readCategoriesMetadata()
106
112
  process = ParseAllThread(self.testDB, self)
107
113
  self.threadPool.start(process)
108
114
 
109
- @QtCore.Slot(Path)
110
- def onSheetPathChanged(self, sheet: Path) -> None:
111
- logger.debug("Slot, new Spreadsheet triggered")
112
- 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
113
122
  self.mainPath = sheet.parent
114
- svgFolder = self.mainPath / self.settings.get(Tags.PICTURESUBFOLDER)
115
- svgFolder.resolve()
116
- self.settings.set(Tags.PICTUREFOLDER, svgFolder)
117
123
  self.ui.buttonSpreadsheet.setText(f"../{sheet.name}")
124
+ self.testDB.spreadsheet = sheet
125
+ self.qSettings.setValue(Tags.SPREADSHEETPATH.full, sheet)
118
126
  self.parseSpreadsheetAll()
127
+ self.setStatus("[OK] Excel Tabelle wurde eingelesen")
119
128
 
120
129
  def updateLog(self, log) -> None:
121
130
  self.ui.loggerWindow.append(log)
@@ -127,8 +136,16 @@ class MainWindow(QtWidgets.QMainWindow):
127
136
  self.settings.set(Tags.INCLUDEINCATS, False)
128
137
 
129
138
  def closeEvent(self, event) -> None:
130
- self.settings.setValue("windowSize", self.size())
131
- 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
+ )
132
149
 
133
150
  @QtCore.Slot()
134
151
  def onSelectionChanged(self, **args) -> None:
@@ -178,12 +195,7 @@ class MainWindow(QtWidgets.QMainWindow):
178
195
  selectedFilter=("*.ods"),
179
196
  )
180
197
  path = Path(file[0]).resolve(strict=True)
181
- if path.is_file():
182
- self.excelPath = path
183
- self.settings.setSpreadsheet(self.excelPath)
184
- self.setStatus("[OK] Excel Tabelle wurde eingelesen")
185
- else:
186
- self.setStatus("[ERROR] keine Tabelle angegeben")
198
+ self.setSheetPath(path)
187
199
 
188
200
  @QtCore.Slot(Category)
189
201
  def treeRefreshCategory(self, cat: Category) -> None:
@@ -247,7 +259,6 @@ class ParseAllThread(QRunnable):
247
259
 
248
260
  @QtCore.Slot()
249
261
  def run(self) -> None:
250
- self.testDB.readCategoriesMetadata(self.mainApp.spreadSheetPath)
251
- self.testDB.asyncInitAllCategories(self.mainApp.spreadSheetPath)
262
+ self.testDB.asyncInitAllCategories(self.mainApp.excelPath)
252
263
  self.mainApp.setStatus("[OK] Tabellen wurde eingelesen")
253
264
  self.testDB.parseAllQuestions()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: excel2moodle
3
- Version: 0.4.2
3
+ Version: 0.4.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
@@ -1,38 +1,38 @@
1
- excel2moodle/__init__.py,sha256=qdQJY0xbSiEhnmqbgJpqBe0kHec7yLOeAdcArScioE8,1925
1
+ excel2moodle/__init__.py,sha256=mnb-RWgmWIPSBk4S65a_jP6rxntAkTeYxN0ObUJalbQ,1801
2
2
  excel2moodle/__main__.py,sha256=sG4ygwfVFskLQorBn-v98SvasNcPmwl_vLYpruT5Hk8,1175
3
- excel2moodle/logger.py,sha256=hX5ZD_vBi7_eFyA98zomEMtHCEMjPcQRUOhtcavY0Po,3065
3
+ excel2moodle/logger.py,sha256=S9tvSwsOx2xta_AhGKHPNgi5FaiycyUDtkzHlIlNAX8,3193
4
4
  excel2moodle/core/__init__.py,sha256=87BwhtZse72Tk17Ib-V9X2k9wkhmtVnEj2ZmJ9JBAnI,63
5
5
  excel2moodle/core/category.py,sha256=TzntDhEURshxWuI6qc_K_t5bSTLXn6s0n_RA56Basg8,1885
6
- excel2moodle/core/dataStructure.py,sha256=MKT3udbfcP9QW_ZdiJyn3_GtfdpcgyOo9CGZ6pvSlRI,14374
6
+ excel2moodle/core/dataStructure.py,sha256=lmquDdRyMqKxHjbcMOJ83BRs1otXqG9vhNFVfQsljwE,15578
7
7
  excel2moodle/core/etHelpers.py,sha256=G37qplp8tPJxqHNCBrf2Wo0jJZ0aDbxE9slQavqYqd8,2293
8
8
  excel2moodle/core/exceptions.py,sha256=9xfsaIcm6Yej6QAZga0d3DK3jLQejdfgJARuAaG-uZY,739
9
9
  excel2moodle/core/globals.py,sha256=Zm1wcrzQTRnhjrkwgBvo7VjKCFdPMjh-VLSSI5_QCO8,2837
10
10
  excel2moodle/core/numericMultiQ.py,sha256=vr-gYogu2sf2a_Bhvhnu1ZSZFZXM32MfhJesjTkoOQM,2618
11
11
  excel2moodle/core/parser.py,sha256=Ec8bQ0CiiZCIdzQovfH2rce406wmyRmvhpDrCPeQfGU,8112
12
- excel2moodle/core/question.py,sha256=u8hE5UpKO9AUvR3XRz9yohw1XhSyLEfTJENAN4w80-U,10747
13
- excel2moodle/core/settings.py,sha256=b7g7zSI7ACcOG_NI34Nc7uZIX_miL2tO1O6MOd8kJTE,7536
12
+ excel2moodle/core/question.py,sha256=nJDs8SPDRYP6xG4rvo8Bbh1734eQ96DZxVXb7yrT8LM,10802
13
+ excel2moodle/core/settings.py,sha256=JhcgZcOrgFC7P4h9fSXZAApEl_9dE643r5arFpU1HXQ,5808
14
14
  excel2moodle/core/stringHelpers.py,sha256=OzFZ6Eu3PeBLKb61K-aeVfUZmVuBerr9KfyOsuNRd7Y,2403
15
- excel2moodle/core/validator.py,sha256=RwDQ-9Fpc5i2Buy3oorWUAh5zsS5fCF-MjRT4CgcXhY,4698
15
+ excel2moodle/core/validator.py,sha256=ssgkyUwrR-0AGPX1cUqvRwZsGja13J7HQ2W72ltqN-Y,4683
16
16
  excel2moodle/extra/__init__.py,sha256=PM-id60HD21A3IcGC_fCYFihS8osBGZMIJCcN-ZRsIM,293
17
17
  excel2moodle/extra/equationVerification.py,sha256=GLJl1r90d8AAiNy0H2hooZrg3D6aEwNfifYKAe3aGxM,3921
18
18
  excel2moodle/question_types/__init__.py,sha256=81mss0g7SVtnlb-WkydE28G_dEAAf6oT1uB8lpK2-II,1041
19
- excel2moodle/question_types/cloze.py,sha256=wTCaCXCxR_qg909w1jGiBP7-c7qmq7kmriGpAbDnBEA,7673
19
+ excel2moodle/question_types/cloze.py,sha256=hgyv244PChnl7FbxcAMQiC4yzBhV6J3Bg4PHgZQyRmQ,7677
20
20
  excel2moodle/question_types/mc.py,sha256=rHKIKSNeHyto84bI9B3wMKzNJuluplsCmYM4k2HW3wQ,5213
21
21
  excel2moodle/question_types/nf.py,sha256=bMP4IXrhnXmAI0NmjEc7DtX4xGaUbxzLicE2LjeaUho,1150
22
- excel2moodle/question_types/nfm.py,sha256=41dY53vJcFZHoDvNq4Wo7oExHMd3jRF_8dqa2I_pyp0,4950
22
+ excel2moodle/question_types/nfm.py,sha256=VYrQmCsEZqfn0x_coBsDw3XvrUA4sy_yj0WS7Nsffqw,4950
23
23
  excel2moodle/ui/UI_equationChecker.py,sha256=evQDlqCHeooJcAnYjhFCyjlPhfknr7ULGKQwMmqQeJ4,8947
24
24
  excel2moodle/ui/UI_exportSettingsDialog.py,sha256=71xxXEqtewN0ReMfJ5t4gbrX_Bf0VEuxJ_DIV7ZtH94,6045
25
25
  excel2moodle/ui/UI_mainWindow.py,sha256=asWUmKIYqufKUvRuCuA1JoMyv4qfRXyoR70F0331lww,19291
26
26
  excel2moodle/ui/UI_variantDialog.py,sha256=snVaF3_YAc7NWjMRg7NzbjL_PzNbOpt4eiqElkE46io,5414
27
27
  excel2moodle/ui/__init__.py,sha256=4EdGtpzwH3rgw4xW9E5x9kdPQYwKbo9rehHRZTNxCrQ,44
28
- excel2moodle/ui/appUi.py,sha256=xwooDG3A8Ro5mrg-pCvdSR6NCFZYT0dj6dKPRqQfrLo,10382
28
+ excel2moodle/ui/appUi.py,sha256=NXlBcjxHBeUzpU8rvqwN3wxad8AUgpMjXidwwVdC9GM,10863
29
29
  excel2moodle/ui/dialogs.py,sha256=JbQ1y55wbzWVTY0nxdGrUm81AdOIY3PXKgET03Hc6Ys,6760
30
30
  excel2moodle/ui/equationChecker.py,sha256=ANpN7S0llkp6pGL1sKHII1Jc8YUvgDR458UnGVnZZOo,2702
31
31
  excel2moodle/ui/treewidget.py,sha256=az64swVj1yQUsioeaZys32AauvQDdC4EKcqdbbWgL6s,2489
32
32
  excel2moodle/ui/windowDoc.py,sha256=WvzHj6F4JvHP82WlTsyFeOXW024Xq3BUqtp--T4twuI,661
33
- excel2moodle-0.4.2.dist-info/licenses/LICENSE,sha256=ywQqe6Sitymkf2lV2NRcx_aGsaC-KbSl_EfEsRXmNRw,35135
34
- excel2moodle-0.4.2.dist-info/METADATA,sha256=k4bCqH4CxEiRrCUjAf8mCUPB8loLmTkVPfPohgmQqwQ,2951
35
- excel2moodle-0.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- excel2moodle-0.4.2.dist-info/entry_points.txt,sha256=myfMLDThuGgWHMJDPPfILiZqo_7D3fhmDdJGqWOAjPw,60
37
- excel2moodle-0.4.2.dist-info/top_level.txt,sha256=5V1xRUQ9o7UmOCmNoWCZPAuy5nXp3Qbzyqch8fUGT_c,13
38
- excel2moodle-0.4.2.dist-info/RECORD,,
33
+ excel2moodle-0.4.4.dist-info/licenses/LICENSE,sha256=ywQqe6Sitymkf2lV2NRcx_aGsaC-KbSl_EfEsRXmNRw,35135
34
+ excel2moodle-0.4.4.dist-info/METADATA,sha256=NnGjQn0V6gBHcWuIjnleEqTeeFK5zVS0bDpwB6240SE,2951
35
+ excel2moodle-0.4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
+ excel2moodle-0.4.4.dist-info/entry_points.txt,sha256=myfMLDThuGgWHMJDPPfILiZqo_7D3fhmDdJGqWOAjPw,60
37
+ excel2moodle-0.4.4.dist-info/top_level.txt,sha256=5V1xRUQ9o7UmOCmNoWCZPAuy5nXp3Qbzyqch8fUGT_c,13
38
+ excel2moodle-0.4.4.dist-info/RECORD,,