diff --git a/src/export.py b/src/export.py index 94792f2..f0ffba4 100644 --- a/src/export.py +++ b/src/export.py @@ -1,6 +1,6 @@ from browser import document from model.tags import export_tag - +from model.translation import Translation def export_to_xml(model): xml_document = export_entry(model.entry) @@ -46,15 +46,20 @@ def export_entry(entry): # if({}) works uncorrectly in transcrypt - if len(entry.lexical_unit) > 0: + if len(entry.lexical_unit) > 0 and len(entry.lexical_unit['lexemes']) > 0: lexunit = doc.createElement("lexicalUnit") lexunit.setAttribute("id", entry.lexical_unit["id"]) - lexunit.setAttribute("type", "single") - lexeme = doc.createElement("lexeme") - lexeme.setAttribute("lexical_unit_lexeme_id", entry.lexical_unit["id"]) - lexeme.textContent = entry.lexical_unit["text"] - - lexunit.appendChild(lexeme) + lexunit.setAttribute("type", entry.lexical_unit['type']) + for lexeme in entry.lexical_unit["lexemes"]: + lexeme_xml = doc.createElement("lexeme") + lexeme_xml.setAttribute("lexical_unit_lexeme_id", lexeme["id"]) + lexeme_xml.textContent = lexeme["text"] + if len(entry.lexical_unit["lexemes"] > 1): + component = doc.createElement('component') + component.appendChild(lexeme_xml) + lexunit.appendChild(component) + else: + lexunit.appendChild(lexeme_xml) head.appendChild(lexunit) @@ -144,10 +149,11 @@ def export_sense(doc, sense): def export_translation_list(doc, py_parent, xml_parent): for cidx, cluster in enumerate(py_parent.translations): - for translation in cluster: - translation_container = export_translation(doc, translation) - translation_container.setAttribute("cluster", str(cidx + 1)) - xml_parent.appendChild(translation_container) + if len(cluster) > 0: + for translation in cluster: + translation_container = export_translation(doc, translation) + translation_container.setAttribute("cluster", str(cidx + 1)) + xml_parent.appendChild(translation_container) def export_translation(doc, translation): @@ -190,3 +196,145 @@ def _export_label_list(doc, lst): label_el.setAttribute('type', key) result.appendChild(label_el) return result + +def _original_xml_query_selector(selector, entry, doc, parent_selector = selector.rsplit(' ', 1)[0]): + query = entry.original_xml.querySelector(selector) + if query is None: + query = doc.createElement(selector.rsplit(' ', 1)[1]) + entry.original_xml.querySelector(parent_selector).appendChild(query) + return query + +def export_example_to_entry_xml(example, other_examples = None): + parser = __new__(DOMParser()) + doc = parser.parseFromString("", "text/xml") + entry_xml = doc.firstChild + + head = doc.createElement("head") + entry_xml.appendChild(head) + + status = doc.createElement("status") + head.appendChild(status) + + headword = doc.createElement("headword") + head.appendChild(headword) + + lemma = doc.createElement("lemma") + lemma.textContent = " ".join(comp.text for comp in example.components) + lemma.setAttribute("type", "compound") + if example.inner.other_attributes['audio'] is not None: + lemma.setAttribute('audio', example.inner.other_attributes['audio']) + headword.appendChild(lemma) + + homonymy = doc.createElement("homonymy") + headword.appendChild(homonymy) + + lexical_unit = doc.createElement("lexicalUnit") + lexical_unit.setAttribute("type", "MWE") + head.appendChild(lexical_unit) + + if example.inner.other_attributes['structure_id'] != None and len(example.components) <= 3: + lexical_unit.setAttribute("id", example.inner.other_attributes['structure_id']) + for comp in example.components: + lexeme = doc.createElement("lexeme") + lexeme.textContent = comp.text + comp_xml = doc.createElement("component") + lexical_unit.appendChild(comp_xml) + comp_xml.appendChild(lexeme) + + + grammar = doc.createElement("grammar") + category = doc.createElement("category") + grammar.appendChild(category) + head.appendChild(grammar) + + variant_list = doc.createElement("variantList") + head.appendChild(variant_list) + related_entry_list = doc.createElement("relatedEntryList") + head.appendChild(related_entry_list) + label_list = doc.createElement("labelList") + head.appendChild(label_list) + comment = doc.createElement("comment") + head.appendChild(comment) + + body = doc.createElement("body") + entry_xml.appendChild(body) + + sense_list = doc.createElement("senseList") + body.appendChild(sense_list) + + sense = doc.createElement("sense") + sense_list.appendChild(sense) + + sense_label_list = doc.createElement("labelList") + sense.appendChild(sense_label_list) + + first_translation = example.translations[0][0] if len(example.translations) > 0 and len(example.translations[0]) > 0 else Translation() + first_translation_is_valid = False + translation_label_list = doc.createElement("labelList") + + # Add labels to sense if label value isn't kontrastivno or približek else keep them in translation + for key, value in first_translation.tags: + key, value = export_tag(key, value) + label_el = doc.createElement("label") + label_list = translation_label_list if value == "kontrastivno" or value == "približek" else sense_label_list + + label_el.textContent = value + label_el.setAttribute('type', key) + + label_list.appendChild(label_el) + + # Set definition as explanation if explanation in slo + definition_list = doc.createElement("definitionList") + sense.appendChild(definition_list) + for explanation in first_translation.explanationList: + if explanation.language == "slo": + definition = doc.createElement("definition") + definition.setAttribute("type", "indicator") + definition.textContent = explanation.value + definition_list.appendChild(definition) + first_translation.explanationList.remove(explanation) + + translation_container_list = doc.createElement("translationContainerList") + sense.appendChild(translation_container_list) + + translation_container = doc.createElement("translationContainer") + + if len(translation_label_list) > 0: + translation_container.appendChild(translation_label_list) + + if first_translation.translation is not "": + translation = doc.createElement("translation") + translation_container.appendChild(translation) + + translation.textContent = first_translation.translation + translation.setAttribute("targetLang", first_translation.targetLang) + + if first_translation.audio: + translation.setAttribute("audio", first_translation.audio) + + if first_translation.source: + translation.setAttribute("source", first_translation.source) + first_translation_is_valid = True + + if len(first_translation.explanationList) > 0 : + explanation_list = _export_explanation_list(doc, first_translation.explanationList) + translation_container.appendChild(explanation_list) + first_translation_is_valid = True + + if first_translation_is_valid: + translation_container_list.appendChild(translation_container) + + example.translations[0] = example.translations[0][1:] if len(example.translations) > 0 and len(example.translations[0]) > 0 else example.translations[0] + export_translation_list(doc, example, translation_container_list) + if other_examples is not None: + example_container_list = doc.createElement("exampleContainerList") + sense.appendChild(example_container_list) + + for example in other_examples: + example_container = example.export(doc) + translation_container_list = doc.createElement("translationContainerList") + export_translation_list(doc, example, translation_container_list) + example_container.appendChild(translation_container_list) + example_container_list.appendChild(example_container) + + return doc \ No newline at end of file diff --git a/src/message/__init__.py b/src/message/__init__.py index 0e18322..805bc1a 100644 --- a/src/message/__init__.py +++ b/src/message/__init__.py @@ -1,10 +1,10 @@ from message.simple_messages import NoReset, Reset, ModalNotOkClose, ClickMessage, DataChgClickMessage, KeyboardPress, NoAction from message.translation_edit import EditTranslation, MoveRight, MoveLeft, BinTranslation from message.show_messages import ShowEntryLabelsEdit, ShowEditTranslation, ShowSenseLabelEdit, ShowSenseDefinitionEdit, ShowCommentEdit, ShowAddTranslation, ShowExampleEdit, ShowVariantsEdit, ShowHomonymyEdit, ShowRelatedEntriesEdit -from message.simple_edits import EditSenseLabel, EditSenseDefinition, EditComment, AddSenseLabel, AddSense, AddExampleTranslation, DoChosenExamples, AddToLabelList, AddToGenericList, EditVariants, EditHomonymy, EditRelatedEntries, EditEntryLabels, ExampleClusterEdit, ExampleClusterAdd +from message.simple_edits import EditSenseLabel, EditSenseDefinition, EditComment, AddSenseLabel, AddSense, AddExampleTranslation, MoveExamplesToSense, AddToLabelList, AddToGenericList, EditVariants, EditHomonymy, EditRelatedEntries, EditEntryLabels, ExampleClusterEdit, ExampleClusterAdd from message.show_menu import ShowTranslationMenu, ShowSenseMenu, ShowExampleMenu from message.sense_edit import SenseMoveUp, SenseMoveDown, SenseBin, AddMultiwordExample -from message.example_edit import ExampleMoveUp, ExampleMoveDown, ExampleBin, ExampleRoleChange, ExampleComponentSpace, ExampleComponentAdd, ExampleComponentRemove, EditExampleText, ToggleExamples, ToggleClusters +from message.example_edit import ExampleAsNewEntry, ExampleMoveUp, ExampleMoveDown, ExampleBin, ExampleRoleChange, ExampleComponentSpace, ExampleComponentAdd, ExampleComponentRemove, EditExampleText, ToggleExamples, ToggleClusters from message.delete_messages import DeleteComment, DeleteVariants, DeleteHomonymy, DeleteRelatedEntries, DeleteEntryLabels from message.ske_messages import ShowSkeModal, SearchInSkeModal, SkeInsert diff --git a/src/message/example_edit.py b/src/message/example_edit.py index 7b06fc0..03bee6c 100644 --- a/src/message/example_edit.py +++ b/src/message/example_edit.py @@ -3,6 +3,10 @@ from message.simple_messages import DataChgClickMessage, ClickMessage, NoReset from message.message import Message from model.example import Example, ComponentLexeme from model.sense import Sense +from model.entry import Entry +from model.model import Model +import lib.screenful as screenful +from export import export_to_xml, export_example_to_entry_xml @@ -13,6 +17,17 @@ def _get_example_idx(example, model): return (sense, eidx) +class ExampleAsNewEntry(ClickMessage): + def update_model(self, model): + example = self.get_arg(0, Example) + entry_xml = export_example_to_entry_xml(example) + new_entry = Entry() + new_entry.import_xml(entry_xml) + + new_model = Model() + new_model.entry = new_entry + screenful.screenful().Editor['new'](None, export_to_xml(new_model)) + class ExampleMoveUp(DataChgClickMessage): def update_model(self, model): example = self.get_arg(0, Example) @@ -60,7 +75,7 @@ class EditExampleText(Message): if example.newly_created: example.newly_created = False sense.examples.append(example) - + idx = 0 for txt in document.getElementsByClassName("example-component-text"): example.components[idx].text = txt.value diff --git a/src/message/show_menu.py b/src/message/show_menu.py index a80d0b9..1038dc3 100644 --- a/src/message/show_menu.py +++ b/src/message/show_menu.py @@ -57,11 +57,21 @@ class ShowSenseMenu(ShowMenu): class ShowExampleMenu(KeyPlusClickMessage): def update_model_default(self, model): example = self.get_arg(0, Example) - - # if some are chosen, then show modal for choosing senses + + # if some are chosen, then show modal for choosing actions if len(model.chosen_examples) > 0 and example in model.chosen_examples: chosen_examples = model.chosen_examples - model.modal_set(lambda: modals.do_chosen_examples(chosen_examples, model.entry)) + multiword_example = False + + for chosen_example in chosen_examples: + if chosen_example.is_multiword(): + if multiword_example is False: + multiword_example = chosen_example + else: + multiword_example = False + break + + model.modal_set(lambda: modals.do_chosen_examples(chosen_examples, model, multiword_example)) else: model.menu_location = self.menu_location model.menu_target = example diff --git a/src/message/simple_edits.py b/src/message/simple_edits.py index 927c819..6c4a9cc 100644 --- a/src/message/simple_edits.py +++ b/src/message/simple_edits.py @@ -58,7 +58,7 @@ class EditComment(QuestionMessage): model.entry.comment = self.new_text -class DoChosenExamples(Message): +class MoveExamplesToSense(Message): def update_model(self, model): chosen_examples = self.get_arg(0, list) diff --git a/src/model/entry.py b/src/model/entry.py index 5e60489..c3c6fa9 100644 --- a/src/model/entry.py +++ b/src/model/entry.py @@ -42,11 +42,18 @@ class Entry(Data): self.variants = [v.textContent for v in entry_xml.querySelectorAll("head variantList variant")] self.homonymy = [{"value": v.textContent, "name": v.getAttribute("name")} for v in entry_xml.querySelectorAll("head headword homonymy homonymyFeature ")] self.related_entries = [re.textContent for re in entry_xml.querySelectorAll("head relatedEntryList relatedEntry")] - - lex_unit = entry_xml.querySelector("lexical_unit lexeme,lexicalUnit lexeme") - if lex_unit: - self.lexical_unit['id'] = lex_unit.getAttribute("lexical_unit_lexeme_id") - self.lexical_unit['text'] = lex_unit.textContent + lex_units = entry_xml.querySelectorAll("lexical_unit lexeme,lexicalUnit lexeme") + lex_unit_parent = entry_xml.querySelector("lexicalUnit") + self.lexical_unit['lexemes'] = [] + self.lexical_unit['id'] = lex_unit_parent.getAttribute('id') if lex_unit_parent and lex_unit_parent.hasAttribute( + "id") else None + self.lexical_unit['type'] = lex_unit_parent.getAttribute("type") if lex_unit_parent and lex_unit_parent.hasAttribute( + "type") else "single" + for unit in lex_units: + lexical_unit = {} + lexical_unit['id'] = unit.getAttribute("lexical_unit_lexeme_id") + lexical_unit['text'] = unit.textContent + self.lexical_unit['lexemes'].append(lexical_unit) measure = entry_xml.querySelector("measureList measure") if measure: diff --git a/src/model/sense.py b/src/model/sense.py index 4e9e6cc..2566c7f 100644 --- a/src/model/sense.py +++ b/src/model/sense.py @@ -37,7 +37,6 @@ class Sense(Data): def merge_labels(self): return ", ".join(val for _, val in self.labels) - def view(self, model, sense_num): examples = [example.view(model, self) for example in self.examples] diff --git a/src/view/modals.py b/src/view/modals.py index b8cccc6..48e8c3d 100644 --- a/src/view/modals.py +++ b/src/view/modals.py @@ -2,6 +2,11 @@ from lib.snabbdom import h import message from view.modal_templates import * from view.utils import show_toggle_cluster_buttons +from export import export_to_xml, export_example_to_entry_xml +from update import update +from model.entry import Entry +import lib.screenful as screenful +from model.model import Model import model @@ -127,7 +132,37 @@ def edit_comment(comment): return modal_template(big_question("Edit comment", comment), "Comment", (message.EditComment,), (message.DeleteComment,)) -def do_chosen_examples(example_list, entry): +def do_chosen_examples(example_list, model, multiword_example): + if multiword_example is False: + return move_examples_to_sense(example_list, model.entry) + else: + return modal_template([ + h("button.shyButton", {"on": {"click": (lambda: move_to_view(example_list, model))}}, "Premakni v pomen"), + h("button.shyButton", {"on": {"click": (lambda: export_to_new_entry(multiword_example, example_list))}}, + "Izvozi v novo geslo")], "Izberite željeno akcijo", None) + + +def move_to_view(example_list, model): + model.modal_reset() + model.modal_set(lambda: move_examples_to_sense(example_list, model.entry)) + update.view.view(model, True) + + +def export_to_new_entry(multiword_example, example_list): + other_examples = [] + for example in example_list: + if example.is_multiword() is False: + other_examples.append(example) + entry_xml = export_example_to_entry_xml(multiword_example, other_examples if len(example_list) > 0 else None) + new_entry = Entry() + new_entry.import_xml(entry_xml) + + new_model = Model() + new_model.entry = new_entry + screenful.screenful().Editor['new'](None, export_to_xml(new_model)) + + +def move_examples_to_sense(example_list, entry): example_senses = [] for idx, sense in enumerate(entry.senses): for ex in sense.examples: @@ -150,7 +185,7 @@ def do_chosen_examples(example_list, entry): options.append(h("label.checkable", {"attrs": {"for": id_}}, text)) options.append(h("br", {}, [])) - return modal_template(options, "Examples picker", (message.DoChosenExamples, example_list)) + return modal_template(options, "Examples picker", (message.MoveExamplesToSense, example_list)) def ske_list(search_term, data, page_num, senses, ske_kinds): diff --git a/src/view/view.py b/src/view/view.py index de61a85..7ebbb4a 100644 --- a/src/view/view.py +++ b/src/view/view.py @@ -98,11 +98,16 @@ class View: elif type(menu_target) is Example: example = menu_target sense = example_sense(example, entry) - return h("span.popup-menu", { "style": style }, [ + dom_children = [ h("button.shyButton", { "on": {"click": msg(ShowExampleEdit, example, sense)}}, "✎"), h("button.shyButton", { "on": {"click": msg(ExampleMoveUp, example)}}, "↑"), h("button.shyButton", { "on": {"click": msg(ExampleMoveDown, example)}}, "↓"), - h("button.shyButton", { "on": {"click": msg(ExampleBin, example)}}, "🗑")]) + h("button.shyButton", { "on": {"click": msg(ExampleBin, example)}}, "🗑")] + + if example.is_multiword(): + dom_children.insert(1, h("button.shyButton", { "on": {"click": msg(ExampleAsNewEntry, example, sense)}}, "Izvozi v novo geslo")) + + return h("span.popup-menu", { "style": style }, dom_children) else: console.log("Should not be heree!!")