slash-update

This commit is contained in:
codeboss 2024-07-29 10:26:16 +08:00
parent 6f6e75f0f4
commit a6222ab188
12 changed files with 418 additions and 18 deletions

View File

@ -5,7 +5,12 @@
</component>
<component name="ChangeListManager">
<list default="true" id="f609c0f2-cd0d-4eea-87f1-8caf02d3f04f" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/frame/MergeView.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/frame/ReferView.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/parse/StoryMap.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/parse/StorylineCmp.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/entry.py" beforeDir="false" afterPath="$PROJECT_DIR$/entry.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -35,15 +40,61 @@
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Python.MergeView.executor": "Run",
"Python.ReferView.executor": "Run",
"Python.ast_load.executor": "Debug",
"Python.entry.executor": "Run",
"Python.entry.executor": "Debug",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"git-widget-placeholder": "master",
"last_opened_file_path": "D:/Projects/Python/StoryCheckTools"
}
}]]></component>
<component name="RunManager">
<component name="RunManager" selected="Python.entry">
<configuration name="MergeView" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="StoryTools" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/frame" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/frame/MergeView.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="ReferView" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="StoryTools" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/frame" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/frame/ReferView.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="entry" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="StoryTools" />
<option name="ENV_FILES" value="" />
@ -69,13 +120,15 @@
<recent_temporary>
<list>
<item itemvalue="Python.entry" />
<item itemvalue="Python.MergeView" />
<item itemvalue="Python.ReferView" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-python-sdk-50da183f06c8-d3b881c8e49f-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-233.13135.95" />
<option value="bundled-python-sdk-5b207ade9991-746f403e7f0c-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-241.17890.14" />
</set>
</attachedChunks>
</component>

View File

@ -1,17 +1,9 @@
from PyQt5.QtWidgets import QWidget, QApplication
from frame.CompareWindow import CompareWin
from sys import argv
from parse.ast_load import global_ast_path, AstParse
from parse.StoryMap import XAST_ParseTool, storyline_list2map
from parse.ast_load import global_ast_path
tool = AstParse(global_ast_path)
print(tool.generate_time())
storys = tool.peak_storylines()
storys_2 = tool.peak_storylines()
defferent_list = tool.storylines_compare(storys, storys_2)
app = QApplication(argv)
win = CompareWin()
win.load_differents(defferent_list, storys, storys_2)
win.show()
app.exec()
astx = XAST_ParseTool(global_ast_path)
storys = astx.story_list
storys_map = storyline_list2map(storys)
astx.storylines_plait(storys_map)
print(storys_map)

71
frame/MergeView.py Normal file
View File

@ -0,0 +1,71 @@
from PyQt5.QtWidgets import QWidget, QTextEdit, QTabWidget, QSplitter, QApplication, QVBoxLayout
import sys
from frame.ReferView import MemoryNode, RelateReferView, EmptyNode, MemorySkin
from typing import List
from PyQt5.Qt import Qt
class MergeDestination:
def __init__(self, story_name:str, prev: MemoryNode, curr: MemoryNode):
self.prev_node = prev
self.curr_node = curr
self.storyline_name = story_name
pass
class LinesMergeView(QWidget, MemorySkin):
def __init__(self, fdefs: MergeDestination, refdefs: List[MergeDestination], parent):
QWidget.__init__(self, parent)
self.define_line = fdefs
self.refers_line = refdefs
layout = QVBoxLayout(self)
splitter = QSplitter(Qt.Orientation.Vertical, self)
layout.addWidget(splitter)
self.tabs_con: QTabWidget = QTabWidget(self)
splitter.addWidget(self.tabs_con)
self.define_prev: QTextEdit = QTextEdit(self)
self.define_prev.setReadOnly(True)
self.tabs_con.addTab(self.define_prev, fdefs.storyline_name)
self.refers_views: List[RelateReferView] = []
for node in refdefs:
refer_view = RelateReferView(node.prev_node, node.curr_node, self)
self.tabs_con.addTab(refer_view, node.storyline_name)
self.refers_views.append(refer_view)
pass
self.mut_enter = QTextEdit(self)
splitter.addWidget(self.mut_enter)
pass
def load_from_mem(self) -> None:
self.define_prev.setText(self.define_line.prev_node.get_from_memory())
self.mut_enter.setText(self.define_line.curr_node.get_from_memory())
for v in self.refers_views:
v.load_from_mem()
pass
pass
def save_to_mem(self):
self.define_line.curr_node.set_to_memory(self.mut_enter.toPlainText())
for v in self.refers_views:
v.save_to_mem()
pass
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
defx = MergeDestination("page0", EmptyNode(), EmptyNode())
refx0 = MergeDestination("pagex1", EmptyNode(), EmptyNode())
view = LinesMergeView(defx, [refx0], None)
view.show()
app.exec()

82
frame/ReferView.py Normal file
View File

@ -0,0 +1,82 @@
from PyQt5.QtWidgets import QTextEdit, QWidget, QSplitter, QVBoxLayout, QApplication
from PyQt5.Qt import Qt
from abc import abstractmethod
from typing import List
import sys
class MemoryNode:
@abstractmethod
def get_from_memory(self) -> str:
raise NotImplementedError("get_from_memory")
@abstractmethod
def set_to_memory(self, content: str):
raise NotImplementedError("set_to_memmory")
class MemorySkin:
@abstractmethod
def load_from_mem(self) -> None:
raise NotImplementedError("load_from_mem")
@abstractmethod
def save_to_mem(self):
raise NotImplementedError("save_to_mem")
class RelateReferView(QWidget, MemorySkin):
def __init__(self, prev_frefs: MemoryNode, curr_frefs: MemoryNode, parent):
"""
构建引用关系视图
:param prev_frefs: 上游节点
:param curr_frefs: 当前引用节点
"""
QWidget.__init__(self, parent)
self.prev_fragment = prev_frefs
self.curr_fragment = curr_frefs
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
splitter_container = QSplitter(Qt.Orientation.Vertical, self)
layout.addWidget(splitter_container)
self.immut_view: QTextEdit = QTextEdit(self)
self.immut_view.setReadOnly(True)
self.mut_refers: QTextEdit = QTextEdit(self)
splitter_container.addWidget(self.immut_view)
splitter_container.addWidget(self.mut_refers)
pass
def load_from_mem(self):
"""
载入内存内容到视图
"""
self.immut_view.setText(self.prev_fragment.get_from_memory())
self.mut_refers.setText(self.curr_fragment.get_from_memory())
pass
def save_to_mem(self):
"""
保存视图内容到内存
"""
self.prev_fragment.set_to_memory(self.immut_view.toPlainText())
self.curr_fragment.set_to_memory(self.mut_refers.toPlainText())
pass
class EmptyNode(MemoryNode):
def get_from_memory(self) -> str:
return "站位视图内容"
def set_to_memory(self, content: str):
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
view = RelateReferView(EmptyNode(), EmptyNode(), None)
view.show()
app.exec()

Binary file not shown.

149
parse/StoryMap.py Normal file
View File

@ -0,0 +1,149 @@
import xml.dom.minidom as mdom
from typing import List, Tuple, Dict
from enum import Enum
from frame.ReferView import EmptyNode, MemoryNode
class ModifyReason(Enum):
Removed = 0,
Append = 1,
Changed = 2,
Nothing = 4,
class FragmentSlice(EmptyNode):
def __init__(self, def_mark: bool = False, name: str= ""):
self.is_define_node = (def_mark, name)
self.story_refer = ""
self.fragm_refer = ""
self.prev_node: 'FragmentSlice' = None # 上游节点
self.next_node: 'FragmentSlice' = None # 下游节点
self.refers_slice: Dict[str, 'FragmentSlice'] = {} # 引用切面
self.changed_prev_nodes: List[Tuple[ModifyReason, 'FragmentSlice']] = [] # 变更的上游节点
self.text_sections: List[str] = [] # 文本段落
pass
def get_from_memory(self) -> str:
return r"\n".join(self.text_sections)
pass
def set_to_memory(self, content: str):
self.text_sections = content.split(r"\n")
pass
class StoryMap:
def __init__(self, name: str):
self.story_name = name
self.sort_index = 0
self.empty_head = FragmentSlice()
self.slice_list: List[FragmentSlice] = [self.empty_head]
pass
def append_fragment_slice(self, node: FragmentSlice):
self.slice_list[-1].next_node = node
node.prev_node = self.slice_list[-1]
self.slice_list.append(node)
pass
def get_fragment_defined(self, name: str) -> FragmentSlice:
for fit in self.slice_list:
if fit.is_define_node[0]:
if fit.is_define_node[1] == name:
return fit
pass
pass
return None
class XAST_ParseTool:
def __init__(self, ast_path: str):
self.dom_tree = mdom.parse(ast_path)
self.story_list: List[StoryMap] = []
names = self.story_names()
for nm in names:
vinst = self.__extract_empty_storymap(nm)
self.__storynode_initfrags(vinst[0], vinst[1])
self.story_list.append(vinst[0])
pass
def story_names(self) -> List[str]:
"""
获取所有故事名称
:return: List[故事名]
"""
storys = self.dom_tree.getElementsByTagName("story")
values = []
for n in storys:
values.append(n.getAttribute("name"))
pass
return values
def __extract_empty_storymap(self, name: str) -> Tuple[StoryMap, mdom.Element]:
storys = self.dom_tree.getElementsByTagName("story")
for node in storys:
if node.getAttribute("name") == name:
mem_node = StoryMap(name)
mem_node.sort_index = int(node.getAttribute("sort"))
return (mem_node, node)
pass
return None
def __storynode_initfrags(self, node: StoryMap, e: mdom.Element):
first_elem: mdom.Element = e.firstChild
while first_elem != None:
if hasattr(first_elem, "tagName"):
dom_tag = first_elem.tagName
if first_elem.tagName == "fragment":
fnode = FragmentSlice(True, first_elem.getAttribute("name"))
self.__fragmnode_init_desc(fnode, first_elem)
node.append_fragment_slice(fnode)
elif first_elem.tagName == "refer":
fnode = FragmentSlice()
fnode.story_refer = first_elem.getAttribute("story")
fnode.fragm_refer = first_elem.getAttribute("fragment")
self.__fragmnode_init_desc(fnode, first_elem)
node.append_fragment_slice(fnode)
pass
pass
first_elem = first_elem.nextSibling
pass
def __fragmnode_init_desc(self, node: FragmentSlice, e: mdom.Element):
node_elem: mdom.Element = e.firstChild
while node_elem != None:
if hasattr(node_elem, "tagName") and node_elem.tagName == "text-section":
line = node_elem.getAttribute("text")
node.text_sections.append(line)
pass
node_elem = node_elem.nextSibling
pass
pass
def storylines_plait(self, storys: Dict[str, StoryMap]):
for snode in storys.values():
self.__storyline_plait_within(snode, storys)
pass
def __storyline_plait_within(self, story: StoryMap, storys_map: Dict[str, StoryMap]):
for fnode in story.slice_list[1:]:
if not fnode.is_define_node[0]:
sname = fnode.story_refer
fname = fnode.fragm_refer
target_story = storys_map[sname]
target_fragment = target_story.get_fragment_defined(fname)
target_fragment.refers_slice[story.story_name] = fnode
pass
pass
pass
pass
def storyline_list2map(storylines: List[StoryMap]) -> Dict[str, StoryMap]:
retv = {}
for linst in storylines:
retv[linst.story_name] = linst
pass
return retv

53
parse/StorylineCmp.py Normal file
View File

@ -0,0 +1,53 @@
from parse.StoryMap import StoryMap, ModifyReason, FragmentSlice
from typing import Dict, List
class CmpTool:
def __init__(self):
pass
def graph_compare(self, graph_new: Dict[str, StoryMap], graph_old: Dict[str, StoryMap]):
fragments_has_removed = []
for story in graph_old.values():
fragments_has_removed = fragments_has_removed + self.__event_remove_check(graph_new, story)
pass
fragments_has_appended = []
for story in graph_new.values():
fragments_has_appended = fragments_has_appended + self.__event_append_check(graph_old, story)
pass
pass
def __event_remove_check(self, graph_new: Dict[str, StoryMap], story_old: StoryMap) -> List[FragmentSlice]:
list_retv = []
for slice in story_old.slice_list[1:]:
if slice.is_define_node[0]:
s_name = story_old.story_name
f_name = slice.is_define_node[1]
story_findout = graph_new[s_name]
if story_findout is None or story_findout.get_fragment_defined(f_name) is None:
list_retv.append(slice)
pass
pass
pass
return list_retv
def __event_append_check(self, graph_old: Dict[str, StoryMap], story_new: StoryMap) -> List[FragmentSlice]:
list_retv = []
for slice in story_new.slice_list[1:]:
if slice.is_define_node[0]:
s_name = story_new.story_name
f_name = slice.is_define_node[1]
story_findout = graph_old[s_name]
if story_findout is None or story_findout.get_fragment_defined(f_name) is None:
list_retv.append(slice)
pass
pass
pass
return list_retv
def __event_changed_check(self,):

Binary file not shown.