ui_extra_networks_user_metadata.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import datetime
  2. import html
  3. import json
  4. import os.path
  5. import gradio as gr
  6. from modules import infotext_utils, images, sysinfo, errors, ui_extra_networks
  7. class UserMetadataEditor:
  8. def __init__(self, ui, tabname, page):
  9. self.ui = ui
  10. self.tabname = tabname
  11. self.page = page
  12. self.id_part = f"{self.tabname}_{self.page.extra_networks_tabname}_edit_user_metadata"
  13. self.box = None
  14. self.edit_name_input = None
  15. self.button_edit = None
  16. self.edit_name = None
  17. self.edit_description = None
  18. self.edit_notes = None
  19. self.html_filedata = None
  20. self.html_preview = None
  21. self.html_status = None
  22. self.button_cancel = None
  23. self.button_replace_preview = None
  24. self.button_save = None
  25. def get_user_metadata(self, name):
  26. item = self.page.items.get(name, {})
  27. user_metadata = item.get('user_metadata', None)
  28. if not user_metadata:
  29. user_metadata = {'description': item.get('description', '')}
  30. item['user_metadata'] = user_metadata
  31. return user_metadata
  32. def create_extra_default_items_in_left_column(self):
  33. pass
  34. def create_default_editor_elems(self):
  35. with gr.Row():
  36. with gr.Column(scale=2):
  37. self.edit_name = gr.HTML(elem_classes="extra-network-name")
  38. self.edit_description = gr.Textbox(label="Description", lines=4)
  39. self.html_filedata = gr.HTML()
  40. self.create_extra_default_items_in_left_column()
  41. with gr.Column(scale=1, min_width=0):
  42. self.html_preview = gr.HTML()
  43. def create_default_buttons(self):
  44. with gr.Row(elem_classes="edit-user-metadata-buttons"):
  45. self.button_cancel = gr.Button('Cancel')
  46. self.button_replace_preview = gr.Button('Replace preview', variant='primary')
  47. self.button_save = gr.Button('Save', variant='primary')
  48. self.html_status = gr.HTML(elem_classes="edit-user-metadata-status")
  49. self.button_cancel.click(fn=None, _js="closePopup")
  50. def get_card_html(self, name):
  51. item = self.page.items.get(name, {})
  52. preview_url = item.get("preview", None)
  53. if not preview_url:
  54. filename, _ = os.path.splitext(item["filename"])
  55. preview_url = self.page.find_preview(filename)
  56. item["preview"] = preview_url
  57. if preview_url:
  58. preview = f'''
  59. <div class='card standalone-card-preview'>
  60. <img src="{html.escape(preview_url)}" class="preview">
  61. </div>
  62. '''
  63. else:
  64. preview = "<div class='card standalone-card-preview'></div>"
  65. return preview
  66. def relative_path(self, path):
  67. for parent_path in self.page.allowed_directories_for_previews():
  68. if ui_extra_networks.path_is_parent(parent_path, path):
  69. return os.path.relpath(path, parent_path)
  70. return os.path.basename(path)
  71. def get_metadata_table(self, name):
  72. item = self.page.items.get(name, {})
  73. try:
  74. filename = item["filename"]
  75. shorthash = item.get("shorthash", None)
  76. stats = os.stat(filename)
  77. params = [
  78. ('Filename: ', self.relative_path(filename)),
  79. ('File size: ', sysinfo.pretty_bytes(stats.st_size)),
  80. ('Hash: ', shorthash),
  81. ('Modified: ', datetime.datetime.fromtimestamp(stats.st_mtime).strftime('%Y-%m-%d %H:%M')),
  82. ]
  83. return params
  84. except Exception as e:
  85. errors.display(e, f"reading info for {name}")
  86. return []
  87. def put_values_into_components(self, name):
  88. user_metadata = self.get_user_metadata(name)
  89. try:
  90. params = self.get_metadata_table(name)
  91. except Exception as e:
  92. errors.display(e, f"reading metadata info for {name}")
  93. params = []
  94. table = '<table class="file-metadata">' + "".join(f"<tr><th>{name}</th><td>{value}</td></tr>" for name, value in params if value is not None) + '</table>'
  95. return html.escape(name), user_metadata.get('description', ''), table, self.get_card_html(name), user_metadata.get('notes', '')
  96. def write_user_metadata(self, name, metadata):
  97. item = self.page.items.get(name, {})
  98. filename = item.get("filename", None)
  99. basename, ext = os.path.splitext(filename)
  100. with open(basename + '.json', "w", encoding="utf8") as file:
  101. json.dump(metadata, file, indent=4, ensure_ascii=False)
  102. def save_user_metadata(self, name, desc, notes):
  103. user_metadata = self.get_user_metadata(name)
  104. user_metadata["description"] = desc
  105. user_metadata["notes"] = notes
  106. self.write_user_metadata(name, user_metadata)
  107. def setup_save_handler(self, button, func, components):
  108. button\
  109. .click(fn=func, inputs=[self.edit_name_input, *components], outputs=[])\
  110. .then(fn=None, _js="function(name){closePopup(); extraNetworksRefreshSingleCard(" + json.dumps(self.page.name) + "," + json.dumps(self.tabname) + ", name);}", inputs=[self.edit_name_input], outputs=[])
  111. def create_editor(self):
  112. self.create_default_editor_elems()
  113. self.edit_notes = gr.TextArea(label='Notes', lines=4)
  114. self.create_default_buttons()
  115. self.button_edit\
  116. .click(fn=self.put_values_into_components, inputs=[self.edit_name_input], outputs=[self.edit_name, self.edit_description, self.html_filedata, self.html_preview, self.edit_notes])\
  117. .then(fn=lambda: gr.update(visible=True), inputs=[], outputs=[self.box])
  118. self.setup_save_handler(self.button_save, self.save_user_metadata, [self.edit_description, self.edit_notes])
  119. def create_ui(self):
  120. with gr.Box(visible=False, elem_id=self.id_part, elem_classes="edit-user-metadata") as box:
  121. self.box = box
  122. self.edit_name_input = gr.Textbox("Edit user metadata card id", visible=False, elem_id=f"{self.id_part}_name")
  123. self.button_edit = gr.Button("Edit user metadata", visible=False, elem_id=f"{self.id_part}_button")
  124. self.create_editor()
  125. def save_preview(self, index, gallery, name):
  126. if len(gallery) == 0:
  127. return self.get_card_html(name), "There is no image in gallery to save as a preview."
  128. item = self.page.items.get(name, {})
  129. index = int(index)
  130. index = 0 if index < 0 else index
  131. index = len(gallery) - 1 if index >= len(gallery) else index
  132. img_info = gallery[index if index >= 0 else 0]
  133. image = infotext_utils.image_from_url_text(img_info)
  134. geninfo, items = images.read_info_from_image(image)
  135. images.save_image_with_geninfo(image, geninfo, item["local_preview"])
  136. return self.get_card_html(name), ''
  137. def setup_ui(self, gallery):
  138. self.button_replace_preview.click(
  139. fn=self.save_preview,
  140. _js="function(x, y, z){return [selected_gallery_index(), y, z]}",
  141. inputs=[self.edit_name_input, gallery, self.edit_name_input],
  142. outputs=[self.html_preview, self.html_status]
  143. ).then(
  144. fn=None,
  145. _js="function(name){extraNetworksRefreshSingleCard(" + json.dumps(self.page.name) + "," + json.dumps(self.tabname) + ", name);}",
  146. inputs=[self.edit_name_input],
  147. outputs=[]
  148. )