Finish Impress v2 loading, some pre-process left
This commit is contained in:
234
desktop_env/evaluators/metrics/slides.py
Normal file
234
desktop_env/evaluators/metrics/slides.py
Normal file
@@ -0,0 +1,234 @@
|
||||
import logging
|
||||
import xml.etree.ElementTree as ET
|
||||
from math import sqrt
|
||||
|
||||
from pptx import Presentation
|
||||
from pptx.util import Inches
|
||||
|
||||
logger = logging.getLogger("desktopenv.metric.slides")
|
||||
|
||||
|
||||
def check_presenter_console_disable(config_file_path):
|
||||
try:
|
||||
tree = ET.parse(config_file_path)
|
||||
root = tree.getroot()
|
||||
|
||||
namespaces = {
|
||||
'oor': 'http://openoffice.org/2001/registry'
|
||||
}
|
||||
|
||||
for item in root.findall(
|
||||
".//item[@oor:path='/org.openoffice.Office.Impress/Misc/Start']/prop[@oor:name='EnablePresenterScreen']",
|
||||
namespaces):
|
||||
# Check if the value of the configuration item indicates that the presenter console has been disabled
|
||||
presenter_screen_enabled = item.find('value').text
|
||||
if presenter_screen_enabled.lower() == 'false':
|
||||
return 1.
|
||||
else:
|
||||
return 0.
|
||||
return 0.
|
||||
except Exception as e:
|
||||
logger.error(f"Error: {e}")
|
||||
return 0.
|
||||
|
||||
|
||||
def check_image_stretch_and_center(modified_ppt, original_ppt):
|
||||
# fixme: this func is overfit to this example libreoffice_impress
|
||||
# Load the presentations
|
||||
original_pres = Presentation(original_ppt)
|
||||
modified_pres = Presentation(modified_ppt)
|
||||
|
||||
# Get the first slide of each presentation
|
||||
original_slide = original_pres.slides[0]
|
||||
modified_slide = modified_pres.slides[0]
|
||||
|
||||
# Get the image on the first slide of each presentation
|
||||
original_slide_images = [shape for shape in original_slide.shapes if shape.shape_type == 13]
|
||||
modified_slide_images = [shape for shape in modified_slide.shapes if shape.shape_type == 13]
|
||||
|
||||
the_image = original_slide_images[0]
|
||||
|
||||
# Get the images that modified in width and height
|
||||
for modified_image in modified_slide_images:
|
||||
if the_image.image.blob == modified_image.image.blob:
|
||||
the_modified_image = modified_image
|
||||
|
||||
if (abs(the_modified_image.width - original_pres.slide_width) > Inches(0.1) or
|
||||
abs(the_modified_image.height - original_pres.slide_height) > Inches(0.1) or
|
||||
abs(the_modified_image.left - (original_pres.slide_width - the_modified_image.width) / 2) > Inches(0.1) or
|
||||
abs(the_modified_image.top - (original_pres.slide_height - the_modified_image.height) / 2) > Inches(0.1)):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def is_red_color(color):
|
||||
# judge if the color is red
|
||||
print(color.rgb)
|
||||
return color and color.rgb == (255, 0, 0)
|
||||
|
||||
|
||||
def get_master_placeholder_color(prs):
|
||||
# get the color of the placeholder
|
||||
masters = prs.slide_masters
|
||||
for idx, master in enumerate(masters):
|
||||
for placeholder in master.placeholders:
|
||||
if placeholder.has_text_frame and placeholder.text == "<number>":
|
||||
text_frame = placeholder.text_frame
|
||||
|
||||
if text_frame.paragraphs:
|
||||
first_paragraph = text_frame.paragraphs[0]
|
||||
return first_paragraph.font.color
|
||||
return None
|
||||
|
||||
|
||||
def check_slide_numbers_color(pptx_file_path):
|
||||
presentation = Presentation(pptx_file_path)
|
||||
|
||||
for i, slide in enumerate(presentation.slides):
|
||||
for shape in slide.shapes:
|
||||
# check if the shape is a text box
|
||||
if hasattr(shape, "text"):
|
||||
if shape.text.isdigit():
|
||||
# "SlidePlaceholder" is the name of the placeholder in the master slide
|
||||
page_number_text = shape.text
|
||||
font_color = get_master_placeholder_color(presentation)
|
||||
print(font_color)
|
||||
return 1 if font_color is not None and is_red_color(font_color) else 0
|
||||
|
||||
|
||||
def compare_pptx_files(file1_path, file2_path, **options):
|
||||
# todo: not strictly match since not all information is compared because we cannot get the info through pptx
|
||||
prs1 = Presentation(file1_path)
|
||||
prs2 = Presentation(file2_path)
|
||||
|
||||
examine_number_of_slides = options.get("examine_number_of_slides", True)
|
||||
examine_shape = options.get("examine_shape", True)
|
||||
examine_text = options.get("examine_text", True)
|
||||
examine_font_name = options.get("examine_font_name", True)
|
||||
examine_font_size = options.get("examine_font_size", True)
|
||||
examine_font_bold = options.get("examine_font_bold", True)
|
||||
examine_font_italic = options.get("examine_font_italic", True)
|
||||
examine_color_rgb = options.get("examine_color_rgb", True)
|
||||
examine_font_underline = options.get("examine_font_underline", True)
|
||||
|
||||
# compare the number of slides
|
||||
if len(prs1.slides) != len(prs2.slides) and examine_number_of_slides:
|
||||
return False
|
||||
|
||||
# compare the content of each slide
|
||||
for slide1, slide2 in zip(prs1.slides, prs2.slides):
|
||||
# check if the shapes are the same
|
||||
for shape1, shape2 in zip(slide1.shapes, slide2.shapes):
|
||||
if (
|
||||
shape1.left != shape2.left or shape1.top != shape2.top or shape1.width != shape2.width or shape1.height != shape2.height) and examine_shape:
|
||||
return False
|
||||
|
||||
if hasattr(shape1, "text") and hasattr(shape2, "text"):
|
||||
if shape1.text != shape2.text and examine_text:
|
||||
return False
|
||||
|
||||
# check if the paragraphs are the same
|
||||
for para1, para2 in zip(shape1.text_frame.paragraphs, shape2.text_frame.paragraphs):
|
||||
# check if the runs are the same
|
||||
for run1, run2 in zip(para1.runs, para2.runs):
|
||||
if run1.text != run2.text and examine_text:
|
||||
return False
|
||||
|
||||
# check if the font properties are the same
|
||||
if run1.font.name != run2.font.name and examine_font_name:
|
||||
return False
|
||||
|
||||
if run1.font.size != run2.font.size and examine_font_size:
|
||||
return False
|
||||
|
||||
if run1.font.bold != run2.font.bold and examine_font_bold:
|
||||
return False
|
||||
|
||||
if run1.font.italic != run2.font.italic and examine_font_italic:
|
||||
return False
|
||||
|
||||
if run1.font.color.rgb != run2.font.color.rgb and examine_color_rgb:
|
||||
return False
|
||||
|
||||
if run1.font.underline != run2.font.underline and examine_font_underline:
|
||||
return False
|
||||
|
||||
# fixme: Actually there are more properties to be compared, but we cannot get them through pptx
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def check_strikethrough(pptx_path, rules):
|
||||
# Load the presentation
|
||||
presentation = Presentation(pptx_path)
|
||||
|
||||
slide_index_s = rules["slide_index_s"]
|
||||
shape_index_s = rules["shape_index_s"]
|
||||
paragraph_index_s = rules["paragraph_index_s"]
|
||||
|
||||
for slide_index in slide_index_s:
|
||||
# Get the slide
|
||||
slide = presentation.slides[slide_index]
|
||||
|
||||
for shape_index in shape_index_s:
|
||||
# Get the text box
|
||||
paragraphs = slide.shapes[shape_index].text_frame.paragraphs
|
||||
|
||||
for paragraph_index in paragraph_index_s:
|
||||
paragraph = paragraphs[paragraph_index]
|
||||
run = paragraph.runs[0]
|
||||
if 'strike' not in run.font._element.attrib:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def check_slide_orientation_Portrait(pptx_path):
|
||||
presentation = Presentation(pptx_path)
|
||||
|
||||
slide_height = presentation.slide_height
|
||||
slide_width = presentation.slide_width
|
||||
|
||||
if slide_width < slide_height:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def evaluate_presentation_fill_to_rgb_distance(pptx_file, rules):
|
||||
rgb = rules["rgb"]
|
||||
|
||||
def slide_fill_distance_to_rgb(_slide, _rgb):
|
||||
fill = _slide.background.fill
|
||||
if fill.type == 1:
|
||||
r1, g1, b1 = fill.fore_color.rgb
|
||||
r2, g2, b2 = _rgb
|
||||
return sqrt((r1 - r2) ** 2 + (g1 - g2) ** 2 + (b1 - b2) ** 2) / sqrt(255 ** 2 + 255 ** 2 + 255 ** 2)
|
||||
|
||||
return 1
|
||||
|
||||
prs = Presentation(pptx_file)
|
||||
similarity = 1 - sum(slide_fill_distance_to_rgb(slide, rgb) for slide in prs.slides) / len(prs.slides)
|
||||
return similarity
|
||||
|
||||
|
||||
def check_left_panel(accessibility_tree):
|
||||
namespaces = {
|
||||
'st': 'uri:deskat:state.at-spi.gnome.org',
|
||||
'cp': 'uri:deskat:component.at-spi.gnome.org'
|
||||
}
|
||||
|
||||
root = ET.fromstring(accessibility_tree)
|
||||
|
||||
for root_pane in root.iter('root-pane'):
|
||||
for panel in root_pane.iter('panel'):
|
||||
for split_pane in panel.iter('split-pane'):
|
||||
# Get the left panel
|
||||
if split_pane.attrib.get("{{{}}}parentcoord".format(namespaces['cp'])) == "(0, 0)":
|
||||
# Get the visible attribute
|
||||
visible = split_pane.attrib.get("{{{}}}visible".format(namespaces['st']))
|
||||
if visible:
|
||||
# decide if it is left panel
|
||||
return 1.
|
||||
|
||||
return 0.
|
||||
Reference in New Issue
Block a user