zolicsaki commited on
Commit
3ce4a16
·
verified ·
1 Parent(s): 4b4a88a

Delete pptx_utils.py

Browse files
Files changed (1) hide show
  1. pptx_utils.py +0 -695
pptx_utils.py DELETED
@@ -1,695 +0,0 @@
1
- from pptx import Presentation
2
- from pptx.dml.color import RGBColor
3
- from pptx.util import Inches
4
- from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
5
- from pptx.util import Pt
6
- import string
7
- from datetime import datetime
8
- import os
9
- import re
10
-
11
- def clean_leading_numbering(text):
12
- # Remove leading numbering like: "1. ", "1) ", "(1) ", "- 1. ", etc.
13
- return re.sub(r'^[\s\(\-\.\d\)]*', '', text)
14
-
15
- def is_logo_exist(file_path: str):
16
- print(file_path)
17
- if os.path.exists(file_path):
18
- # print("File exists.")
19
- return True
20
- else:
21
- print("File does not exist.")
22
- return False
23
-
24
- class Dict2PPT:
25
- def __init__(self, logo_path: str = 'logo.png', title_size: int = 32, content_size: int=24) -> None:
26
- self.title_font_size = Pt(title_size)
27
- self.content_font_size = Pt(content_size)
28
- self.logo_path = logo_path
29
- self.prs = Presentation()
30
-
31
- def _title_preprocess(self, title: str):
32
- words = title.split()
33
- capitalized_words = [word.capitalize() for word in words]
34
- result = ' '.join(capitalized_words)
35
- return result
36
-
37
- def _add_time_footnote(self, slide):
38
- # Get slide dimensions
39
- slide_width = self.prs.slide_width
40
- slide_height = self.prs.slide_height
41
-
42
- # Prepare date text
43
- date_str = datetime.today().strftime("%B %d, %Y") # e.g., March 26, 2025
44
-
45
- # Set textbox size
46
- textbox_width = Inches(3) # You can adjust this
47
- textbox_height = Inches(0.3)
48
- left = (slide_width - textbox_width) / 2 # Center horizontally
49
- top = slide_height - Inches(0.5) # Near bottom
50
-
51
- textbox = slide.shapes.add_textbox(left, top, textbox_width, textbox_height)
52
- text_frame = textbox.text_frame
53
- p = text_frame.paragraphs[0]
54
- run = p.add_run()
55
- run.text = date_str
56
- run.font.size = Pt(12)
57
- p.alignment = PP_ALIGN.CENTER # ✅ Center text horizontally
58
-
59
- def _add_logo(self, slide):
60
- # Define logo path and size
61
- # logo_path = "logo.png" # Replace with your actual logo path
62
-
63
- if not is_logo_exist(file_path=self.logo_path):
64
- return
65
- logo_width = Inches(1.0) # Resize logo as needed
66
- logo_height = Inches(1.0)
67
-
68
- # Calculate position for top-right corner
69
- slide_width = self.prs.slide_width
70
- right_margin = Inches(0.2) # Optional small margin from edge
71
- top = Inches(0.2)
72
-
73
- # Position: from right edge minus logo width
74
- left = slide_width - logo_width - right_margin
75
-
76
- # Add logo
77
- slide.shapes.add_picture(self.logo_path, left, top, width=logo_width, height=logo_height)
78
-
79
- def _set_background_color(self, slide):
80
- fill = slide.background.fill
81
- fill.solid() # Use solid color
82
- fill.fore_color.rgb = RGBColor(240, 248, 255) # RGB for a light blue
83
-
84
- def title_slide(self, title: str, authors: str):
85
- title_slide_layout = self.prs.slide_layouts[0] # Title Slide
86
- slide = self.prs.slides.add_slide(title_slide_layout)
87
-
88
- self._set_background_color(slide=slide)
89
- self._add_logo(slide=slide)
90
-
91
- title_shape = slide.shapes.title
92
- title_shape.text = title
93
- title_paragraph = title_shape.text_frame.paragraphs[0]
94
- for run in title_paragraph.runs:
95
- run.font.bold = True
96
- run.font.name = 'Times New Roman'
97
- run.font.size = Pt(36) # e.g., 44 pt
98
-
99
- author_shape = slide.placeholders[1]
100
- today = datetime.today().strftime("%B %d, %Y") # e.g., March 25, 2025
101
- # print('authors', authors)
102
- # if authors:
103
- # author_shape.text = '\n' + authors + '\n' + today
104
- # else:
105
- # author_shape.text = '\nAuthor Here\n' + today
106
- author_shape.text = '\nAuthor Here\n' + today
107
- # Set subtitle font size
108
- author_paragraph = author_shape.text_frame.paragraphs[1] # 0 is blank line, 1 is actual text
109
- for run in author_paragraph.runs:
110
- run.font.name = 'Times New Roman'
111
- run.font.size = Pt(24) # Set subtitle font size to 28 pt
112
-
113
- def outline_slide(self, outline: dict):
114
- content_slide_layout = self.prs.slide_layouts[1] # title and Content Slide Layout
115
- slide = self.prs.slides.add_slide(content_slide_layout)
116
- self._set_background_color(slide=slide)
117
- self._add_logo(slide=slide)
118
- title_shape = slide.shapes.title
119
- title_shape.text = 'Outline'
120
- title_paragraph = title_shape.text_frame.paragraphs[0]
121
- title_paragraph.alignment = PP_ALIGN.LEFT
122
- for run in title_paragraph.runs:
123
- run.font.bold = True
124
- run.font.name = 'Times New Roman'
125
- run.font.size = Pt(36) # e.g., 36 pt
126
-
127
- # Clear existing content
128
- content_shape = slide.placeholders[1]
129
- text_frame = content_shape.text_frame
130
- text_frame.clear()
131
-
132
- # Add topic
133
- for topic, desc in outline.items():
134
- p1 = text_frame.add_paragraph()
135
- p1.text = topic
136
- p1.level = 0
137
- p1.font.size = Pt(20)
138
- p1.font.name = 'Times New Roman'
139
- p1.font.bold = True
140
- p1.alignment = PP_ALIGN.LEFT
141
-
142
- # Line 2: description (indented)
143
- if len(desc) > 0:
144
- p2 = text_frame.add_paragraph()
145
- p2.text = desc
146
- p2.level = 1 # Indented bullet
147
- p2.font.size = Pt(12)
148
- p2.font.name = 'Times New Roman'
149
- p2.alignment = PP_ALIGN.LEFT
150
-
151
- self._add_time_footnote(slide=slide)
152
-
153
- def _outline_preprocess_(self, outline):
154
- if isinstance(outline, dict):
155
- clean_outline = {}
156
- for topic, desc in outline.items():
157
- topic = topic.strip().strip(string.punctuation).strip()
158
- desc = desc.strip().strip(string.punctuation).strip()
159
- clean_outline[topic] = desc
160
- return clean_outline
161
-
162
- elif isinstance(outline, str):
163
- sentences = outline.split('\n')
164
- sentences = [text.strip().strip(string.punctuation).strip() for text in sentences]
165
- sent_dict = {}
166
- for sent in sentences:
167
- tokens = sent.split(':')
168
- if len(tokens) == 1:
169
- sent_dict[tokens[0]] = ''
170
- else:
171
- key = tokens[0].strip().strip(string.punctuation).strip()
172
- value = ''.join(tokens[1:])
173
- value = value.strip().strip(string.punctuation).strip()
174
- sent_dict[key] = value
175
- return sent_dict
176
- else:
177
- print('Wrong format')
178
- return {}
179
-
180
- def _background_preprocess(self, background: str):
181
- background_array = []
182
- sentences = background.strip().splitlines()
183
- for sent in sentences:
184
- sent = clean_leading_numbering(sent)
185
- background_array.append(sent.strip().strip(string.punctuation).strip())
186
- return background_array
187
-
188
- def background_slide(self, background):
189
- content_slide_layout = self.prs.slide_layouts[1] # title and Content Slide Layout
190
- slide = self.prs.slides.add_slide(content_slide_layout)
191
- self._set_background_color(slide=slide)
192
- self._add_logo(slide=slide)
193
- title_shape = slide.shapes.title
194
- title_shape.text = 'Background'
195
- title_paragraph = title_shape.text_frame.paragraphs[0]
196
- title_paragraph.alignment = PP_ALIGN.LEFT
197
- for run in title_paragraph.runs:
198
- run.font.bold = True
199
- run.font.name = 'Times New Roman'
200
- run.font.size = Pt(36) # e.g., 36 pt
201
-
202
- # Clear existing content
203
- content_shape = slide.placeholders[1]
204
- text_frame = content_shape.text_frame
205
- text_frame.clear()
206
- # ✅ Vertically center content inside the placeholder
207
- text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE
208
-
209
- # Add topic + indented description as two lines
210
- background_item_num = len(background)
211
- fontsize = 22
212
- if background_item_num >= 4 and background_item_num <= 6:
213
- fontsize = 20
214
- elif background_item_num >7:
215
- fontsize = 18
216
- for idx, topic in enumerate(background, start=1):
217
- p1 = text_frame.add_paragraph()
218
- p1.text = f"{idx}. {topic}"
219
- p1.level = 0
220
- p1.font.size = Pt(fontsize)
221
- p1.font.name = 'Times New Roman'
222
- # p1.font.bold = True
223
- p1.alignment = PP_ALIGN.LEFT
224
-
225
- self._add_time_footnote(slide=slide)
226
-
227
- def _problem_define_preprocess(self, problem_desc: str):
228
- from collections import OrderedDict
229
- def split_text_by_headers(text, headers):
230
- sections = OrderedDict({header: [] for header in headers})
231
- current = None
232
- for line in text.strip().strip(string.punctuation).splitlines():
233
- line_clean = line.strip().strip(string.punctuation).strip()
234
- if len(line_clean) == 0:
235
- continue
236
- # Check if line matches any of the section headers
237
- matched = [h for h in headers if h.lower() == line_clean.lower()]
238
- if matched:
239
- current = matched[0]
240
- continue
241
- if current:
242
- cleaned_line = clean_leading_numbering(text=line_clean)
243
- cleaned_line = cleaned_line.strip().strip(string.punctuation).strip()
244
- sections[current].append(cleaned_line)
245
-
246
- # Convert lists to joined text blocks
247
- return {k: v for k, v in sections.items()}
248
-
249
- sections = ["Scope", "Challenges", "Assumptions", "Relevance"]
250
- problem_dict = {}
251
- if any([_ in problem_desc for _ in sections]):
252
- problem_dict = split_text_by_headers(text=problem_desc, headers=sections)
253
-
254
- if all([len(v)==0 for k, v in problem_dict.items()]) or len(problem_dict) == 0:
255
- problem_dict = {}
256
- cleaned_sentences = []
257
- sentences = problem_desc.strip().strip(string.punctuation).splitlines()
258
- for sent in sentences:
259
- cleaned_line = clean_leading_numbering(text=sent)
260
- cleaned_line = cleaned_line.strip().strip(string.punctuation).strip()
261
- cleaned_sentences.append(cleaned_line)
262
- problem_dict['Scope'] = cleaned_sentences
263
-
264
- return problem_dict
265
-
266
- def problem_def_slide(self, problems):
267
- sections = ["Scope", "Challenges", "Assumptions", "Relevance"]
268
- scope = problems.get('Scope', [])
269
- challenges = problems.get('Challenges', [])
270
- assumptions = problems.get('Assumptions', [])
271
- relevance = problems.get('Relevance', [])
272
- for sect_name in sections:
273
- section_contents = problems.get(sect_name, [])
274
- if len(section_contents) == 0:
275
- continue
276
- content_slide_layout = self.prs.slide_layouts[1] # title and Content Slide Layout
277
- slide = self.prs.slides.add_slide(content_slide_layout)
278
- self._set_background_color(slide=slide)
279
- self._add_logo(slide=slide)
280
- title_shape = slide.shapes.title
281
- if sect_name == 'Scope':
282
- title_shape.text = 'Problem Definition'
283
- elif sect_name in {'Challenges', 'Assumptions'}:
284
- title_shape.text = 'Problem Definition - {}'.format(sect_name)
285
- else:
286
- title_shape.text = 'Interested Practitioners'
287
- title_paragraph = title_shape.text_frame.paragraphs[0]
288
- title_paragraph.alignment = PP_ALIGN.LEFT
289
- for run in title_paragraph.runs:
290
- run.font.bold = True
291
- run.font.name = 'Times New Roman'
292
- run.font.size = Pt(36) # e.g., 36 pt
293
-
294
- # Clear existing content
295
- content_shape = slide.placeholders[1]
296
- text_frame = content_shape.text_frame
297
- text_frame.clear()
298
- # ✅ Vertically center content inside the placeholder
299
- text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE
300
- fontsize = 20
301
- for idx, topic in enumerate(section_contents, start=1):
302
- p1 = text_frame.add_paragraph()
303
- p1.text = f"{idx}. {topic}"
304
- p1.level = 0
305
- p1.font.size = Pt(fontsize)
306
- p1.font.name = 'Times New Roman'
307
- # p1.font.bold = True
308
- p1.alignment = PP_ALIGN.LEFT
309
-
310
- self._add_time_footnote(slide=slide)
311
-
312
- def _objective_preprocess(self, objective: str):
313
- objective_array = []
314
- sentences = objective.strip().splitlines()
315
- for sent in sentences:
316
- sent = clean_leading_numbering(text=sent)
317
- objective_array.append(sent.strip().strip(string.punctuation).strip())
318
- return objective_array
319
-
320
- def objective_slide(self, objectives):
321
- content_slide_layout = self.prs.slide_layouts[1] # title and Content Slide Layout
322
- slide = self.prs.slides.add_slide(content_slide_layout)
323
- self._set_background_color(slide=slide)
324
- self._add_logo(slide=slide)
325
- title_shape = slide.shapes.title
326
- title_shape.text = 'Objectives & How'
327
- title_paragraph = title_shape.text_frame.paragraphs[0]
328
- title_paragraph.alignment = PP_ALIGN.LEFT
329
- for run in title_paragraph.runs:
330
- run.font.bold = True
331
- run.font.name = 'Times New Roman'
332
- run.font.size = Pt(36) # e.g., 36 pt
333
-
334
- # Clear existing content
335
- content_shape = slide.placeholders[1]
336
- text_frame = content_shape.text_frame
337
- text_frame.clear()
338
- # ✅ Vertically center content inside the placeholder
339
- text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE
340
-
341
- objective_item_num = len(objectives)
342
- fontsize = 24
343
- if objective_item_num >= 4 and objective_item_num <= 6:
344
- fontsize = 22
345
- elif objective_item_num >7:
346
- fontsize = 20
347
- for idx, topic in enumerate(objectives, start=1):
348
- p1 = text_frame.add_paragraph()
349
- p1.text = f"{idx}. {topic}"
350
- p1.level = 0
351
- p1.font.size = Pt(fontsize)
352
- p1.font.name = 'Times New Roman'
353
- # p1.font.bold = True
354
- p1.alignment = PP_ALIGN.LEFT
355
-
356
- self._add_time_footnote(slide=slide)
357
-
358
- def _method_preprocess(self, methodology: str):
359
- method_array = []
360
- sentences = methodology.strip().splitlines()
361
- for sent in sentences:
362
- sent_trim = clean_leading_numbering(text=sent)
363
- sent_trim = sent_trim.strip().strip(string.punctuation).strip()
364
- method_array.append(sent_trim)
365
- return method_array
366
-
367
- def method_slide(self, methods):
368
- content_slide_layout = self.prs.slide_layouts[1] # title and Content Slide Layout
369
- slide = self.prs.slides.add_slide(content_slide_layout)
370
- self._set_background_color(slide=slide)
371
- self._add_logo(slide=slide)
372
-
373
- title_shape = slide.shapes.title
374
- title_shape.text = 'Proposed Method'
375
- title_paragraph = title_shape.text_frame.paragraphs[0]
376
- title_paragraph.alignment = PP_ALIGN.LEFT
377
- for run in title_paragraph.runs:
378
- run.font.bold = True
379
- run.font.name = 'Times New Roman'
380
- run.font.size = Pt(36) # e.g., 36 pt
381
-
382
- # Clear existing content
383
- content_shape = slide.placeholders[1]
384
- text_frame = content_shape.text_frame
385
- text_frame.clear()
386
- # ✅ Vertically center content inside the placeholder
387
- text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE
388
-
389
- fontsize = 20
390
- for idx, step in enumerate(methods, start=1):
391
- p = text_frame.add_paragraph()
392
- run1 = p.add_run()
393
- run1.text = "Step {}. ".format(idx)
394
- run1.font.bold = True
395
- run1.font.size = Pt(fontsize)
396
-
397
- # Second run: normal text
398
- run2 = p.add_run()
399
- run2.text = step
400
- run2.font.bold = False
401
- run2.font.size = Pt(fontsize)
402
- p.font.name = 'Times New Roman'
403
- p.alignment = PP_ALIGN.LEFT
404
-
405
- self._add_time_footnote(slide=slide)
406
-
407
- def _experiment_preprocess(self, experiment: str):
408
- def split_sections_by_keywords(text: str, keyword1: str, keyword2: str) -> dict:
409
- lines = text.strip().splitlines()
410
- part1_lines = []
411
- part2_lines = []
412
- current_section = None
413
- for line in lines:
414
- stripped = clean_leading_numbering(line)
415
- stripped = stripped.strip().strip(string.punctuation).strip()
416
- if len(stripped) == 0:
417
- continue
418
- if keyword1 in stripped:
419
- current_section = keyword1
420
- continue
421
- elif keyword2 in stripped:
422
- current_section = keyword2
423
- continue
424
-
425
- if current_section == keyword1:
426
- tokens = stripped.split(':')
427
- key = tokens[0].strip().strip(string.punctuation).strip()
428
- if len(tokens) > 1:
429
- parse_stripped = key + ": " + ':'.join(tokens[1:]).strip().strip(string.punctuation).strip()
430
- else:
431
- parse_stripped = key
432
- part1_lines.append(parse_stripped)
433
- elif current_section == keyword2:
434
- tokens = stripped.split(':')
435
- key = tokens[0].strip().strip(string.punctuation).strip()
436
- if len(tokens) > 1:
437
- parse_stripped = (key, ':'.join(tokens[1:]))
438
- else:
439
- parse_stripped = (key, '')
440
- part2_lines.append(parse_stripped)
441
- return {
442
- keyword1: part1_lines,
443
- keyword2: part2_lines
444
- }
445
-
446
- experiment_dict = {}
447
- sentences = experiment.strip().splitlines()
448
- evidence_keyword = 'Evidence Summary'
449
- exp_summary_keyword = 'Experimental Summary'
450
- if (evidence_keyword in experiment) and (exp_summary_keyword in experiment):
451
- experiment_dict = split_sections_by_keywords(text=experiment, keyword1=evidence_keyword, keyword2=exp_summary_keyword)
452
- else:
453
- experiment_array = []
454
- for sent in sentences:
455
- sent = clean_leading_numbering(sent)
456
- sent = sent.strip().strip(string.punctuation).strip()
457
- experiment_array.append(sent)
458
- experiment_dict[exp_summary_keyword] = experiment_array
459
- return experiment_dict
460
-
461
- def experiment_slide(self, experiments):
462
- evidence_keyword = 'Evidence Summary'
463
- exp_summary_keyword = 'Experimental Summary'
464
- if len(experiments) == 1:
465
- experiments_part1 = experiments[exp_summary_keyword]
466
- experiments_part2 = []
467
- else:
468
- assert len(experiments) == 2
469
- experiments_part1 = experiments[exp_summary_keyword]
470
- experiments_part2 = experiments[evidence_keyword]
471
-
472
- content_slide_layout = self.prs.slide_layouts[1] # title and Content Slide Layout
473
- slide = self.prs.slides.add_slide(content_slide_layout)
474
- self._set_background_color(slide=slide)
475
- self._add_logo(slide=slide)
476
- title_shape = slide.shapes.title
477
- title_shape.text = 'Experimental Study'
478
- title_paragraph = title_shape.text_frame.paragraphs[0]
479
- title_paragraph.alignment = PP_ALIGN.LEFT
480
- for run in title_paragraph.runs:
481
- run.font.bold = True
482
- run.font.name = 'Times New Roman'
483
- run.font.size = Pt(36) # e.g., 36 pt
484
-
485
- # Clear existing content
486
- content_shape = slide.placeholders[1]
487
- text_frame = content_shape.text_frame
488
- text_frame.clear()
489
- # ✅ Vertically center content inside the placeholder
490
- text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE
491
-
492
- fontsize = 20
493
- if len(experiments_part2) == 0:
494
- for idx, sent in enumerate(experiments_part1, start=1):
495
- p1 = text_frame.add_paragraph()
496
- p1.text = f"{idx}. {sent}"
497
- p1.level = 0
498
- p1.font.size = Pt(fontsize)
499
- p1.font.name = 'Times New Roman'
500
- p1.font.bold = True
501
- p1.alignment = PP_ALIGN.LEFT
502
- else:
503
- for idx, step in enumerate(experiments_part1, start=1):
504
- key, value = step
505
- if len(value) == 0:
506
- continue
507
- p = text_frame.add_paragraph()
508
- run1 = p.add_run()
509
- run1.text = key
510
- run1.font.bold = True
511
- run1.font.size = Pt(fontsize)
512
-
513
- # Second run: normal text
514
- run2 = p.add_run()
515
- run2.text = value
516
- run2.font.bold = False
517
- run2.font.size = Pt(fontsize)
518
- p.font.name = 'Times New Roman'
519
- p.alignment = PP_ALIGN.LEFT
520
-
521
- self._add_time_footnote(slide=slide)
522
-
523
- ###experimental study in multiple pages
524
- if len(experiments_part2) > 0:
525
- content_slide_layout = self.prs.slide_layouts[1] # title and Content Slide Layout
526
- slide_2 = self.prs.slides.add_slide(content_slide_layout)
527
- self._set_background_color(slide=slide_2)
528
- self._add_logo(slide=slide_2)
529
- title_shape = slide_2.shapes.title
530
- title_shape.text = 'Experimental Study (Summary)'
531
- title_paragraph = title_shape.text_frame.paragraphs[0]
532
- title_paragraph.alignment = PP_ALIGN.LEFT
533
- for run in title_paragraph.runs:
534
- run.font.bold = True
535
- run.font.name = 'Times New Roman'
536
- run.font.size = Pt(36) # e.g., 36 pt
537
-
538
- # Clear existing content
539
- content_shape = slide_2.placeholders[1]
540
- text_frame = content_shape.text_frame
541
- text_frame.clear()
542
- # ✅ Vertically center content inside the placeholder
543
- text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE
544
- self._add_time_footnote(slide=slide_2)
545
- for idx, sent in enumerate(experiments_part2, start=1):
546
- p1 = text_frame.add_paragraph()
547
- p1.text = f"{idx}. {sent}"
548
- p1.level = 0
549
- p1.font.size = Pt(fontsize)
550
- p1.font.name = 'Times New Roman'
551
- p1.alignment = PP_ALIGN.LEFT
552
-
553
- def _conclusion_preprocess(self, conclusion: str):
554
- conclusion_dict = {}
555
- sentences = conclusion.strip().splitlines()
556
- for sent in sentences:
557
- trim_sent = sent.strip().strip(string.punctuation).strip()
558
- trim_sent = clean_leading_numbering(text=trim_sent)
559
- if len(trim_sent) == 0 or trim_sent.lower().startswith('conclusion'):
560
- continue
561
- else:
562
- tokens = trim_sent.split(':')
563
- key = tokens[0].strip().strip(string.punctuation).strip()
564
- if len(tokens) == 1:
565
- conclusion_dict[key] = ''
566
- else:
567
- value = ':'.join(tokens[1:]).strip().strip(string.punctuation).strip()
568
- conclusion_dict[key] = value
569
- return conclusion_dict
570
-
571
- def conclusion_slide(self, conclusion):
572
- content_slide_layout = self.prs.slide_layouts[1] # title and Content Slide Layout
573
- slide = self.prs.slides.add_slide(content_slide_layout)
574
- self._set_background_color(slide=slide)
575
- self._add_logo(slide=slide)
576
- title_shape = slide.shapes.title
577
- title_shape.text = 'Conclusions & Future Work'
578
- title_paragraph = title_shape.text_frame.paragraphs[0]
579
- title_paragraph.alignment = PP_ALIGN.LEFT
580
- for run in title_paragraph.runs:
581
- run.font.bold = True
582
- run.font.name = 'Times New Roman'
583
- run.font.size = Pt(36) # e.g., 36 pt
584
-
585
- # Clear existing content
586
- content_shape = slide.placeholders[1]
587
- text_frame = content_shape.text_frame
588
- text_frame.clear()
589
- # ✅ Vertically center content inside the placeholder
590
- text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE
591
-
592
- # Add topic
593
- for topic, desc in conclusion.items():
594
- if len(desc) == 0:
595
- continue
596
- p1 = text_frame.add_paragraph()
597
- p1.text = topic
598
- p1.level = 0
599
- p1.font.size = Pt(20)
600
- p1.font.name = 'Times New Roman'
601
- p1.font.bold = True
602
- p1.alignment = PP_ALIGN.LEFT
603
-
604
- # Line 2: description (indented)
605
- p2 = text_frame.add_paragraph()
606
- p2.text = desc
607
- p2.level = 1 # Indented bullet
608
- p2.font.size = Pt(16)
609
- p2.font.italic = True
610
- p2.font.name = 'Times New Roman'
611
- p2.alignment = PP_ALIGN.LEFT
612
-
613
- self._add_time_footnote(slide=slide)
614
-
615
- def build_slides(self, slide_dict: dict, authors: str = 'Author here'):
616
- title = slide_dict.get('Title', '')
617
- title = self._title_preprocess(title=title)
618
- self.title_slide(title=title, authors=authors)
619
-
620
- outline = slide_dict.get('Outline', {})
621
- outline = self._outline_preprocess_(outline=outline)
622
- assert len(outline) > 0, 'No outline detected!!!'
623
- self.outline_slide(outline=outline)
624
-
625
- background = slide_dict.get('Background', '')
626
- if background:
627
- background = self._background_preprocess(background=background)
628
- self.background_slide(background=background)
629
-
630
- problem_definition = slide_dict.get('Research problem', '')
631
- # print('problem_definition', problem_definition)
632
- if problem_definition:
633
- problems = self._problem_define_preprocess(problem_desc=problem_definition)
634
- # print('problems', problems)
635
- self.problem_def_slide(problems=problems)
636
-
637
- objectives = slide_dict.get('Objectives', '')
638
- if objectives:
639
- objectives = self._objective_preprocess(objective=objectives)
640
- self.objective_slide(objectives=objectives)
641
-
642
- methodology = slide_dict.get('Methodology', '')
643
- if methodology:
644
- methodology = self._method_preprocess(methodology=methodology)
645
- # print('Method', methodology)
646
- self.method_slide(methods=methodology)
647
-
648
- experimental_study = slide_dict.get('Results', '')
649
- if experimental_study:
650
- experiments = self._experiment_preprocess(experiment=experimental_study)
651
- # print('experiments', experiments)
652
- self.experiment_slide(experiments=experiments)
653
-
654
- conclusion = slide_dict.get('Conclusions', '')
655
- if conclusion:
656
- conclusion = self._conclusion_preprocess(conclusion=conclusion)
657
- self.conclusion_slide(conclusion=conclusion)
658
-
659
- self.qa_slides()
660
- print('Done!!')
661
-
662
- def qa_slides(self):
663
- # Add a blank slide (usually layout 6 is blank)
664
- blank_slide_layout = self.prs.slide_layouts[6]
665
- slide = self.prs.slides.add_slide(blank_slide_layout)
666
- self._set_background_color(slide=slide)
667
- self._add_logo(slide=slide)
668
-
669
- # Add a textbox in the center
670
- left = Inches(2)
671
- top = Inches(2.5)
672
- width = Inches(6)
673
- height = Inches(2)
674
-
675
- textbox = slide.shapes.add_textbox(left, top, width, height)
676
- text_frame = textbox.text_frame
677
- text_frame.clear()
678
-
679
- # Add "Thank you"
680
- p1 = text_frame.add_paragraph()
681
- p1.text = "Thank you!"
682
- p1.font.size = Pt(44)
683
- p1.font.bold = True
684
- p1.alignment = PP_ALIGN.CENTER
685
-
686
- # Add "Q & A"
687
- p2 = text_frame.add_paragraph()
688
- p2.text = "\nQ & A"
689
- p2.font.size = Pt(36)
690
- p2.alignment = PP_ALIGN.CENTER
691
-
692
- self._add_time_footnote(slide=slide)
693
-
694
- def save(self, file_name='slides.pptx'):
695
- self.prs.save(file_name)