From 48823b36a4b1dd2d26d45d6b34d2e26083b9c39e Mon Sep 17 00:00:00 2001
From: Mattkmmr <49940207+Mattkmmr@users.noreply.github.com>
Date: Wed, 22 Dec 2021 10:59:57 +0100
Subject: [PATCH 1/2] Modifications by George Baynes

---
 MediaReport/media_report.py | 203 +++++++++++++++++-------------------
 1 file changed, 95 insertions(+), 108 deletions(-)

diff --git a/MediaReport/media_report.py b/MediaReport/media_report.py
index 15242a3da..cc5ba8ce7 100644
--- a/MediaReport/media_report.py
+++ b/MediaReport/media_report.py
@@ -17,7 +17,12 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 #
-
+"""
+1.0 Matthias Kemmer
+1.1 George Baynes (baynes@ntlworld.com) adapted to give .odt .ps output
+    it still fails .rtf .txt .html and print due to attempt to find available
+    width or height. Unable to check latex output.
+"""
 
 # ----------------------------------------------------------------------------
 #
@@ -25,6 +30,7 @@
 #
 # ----------------------------------------------------------------------------
 import os
+import time
 from math import floor
 
 # ----------------------------------------------------------------------------
@@ -38,9 +44,11 @@
 from gramps.gen.display.name import displayer as name_displayer
 from gramps.gen.plug.menu import (MediaOption, NoteOption, BooleanOption,
                                   StringOption, NumberOption)
-from gramps.gen.plug.docgen import (ParagraphStyle, FontStyle, TableStyle,
-                                    TableCellStyle, PARA_ALIGN_CENTER,
-                                    PARA_ALIGN_LEFT)
+from gramps.gen.plug.docgen import (ParagraphStyle, FontStyle, PARA_ALIGN_CENTER,
+                                    IndexMark, FONT_SERIF,
+                                    FONT_SANS_SERIF, INDEX_TYPE_TOC, TableStyle,
+                                    TableCellStyle)
+from gramps.gen.plug.report.utils import pt2cm
 
 # Old:
 #from gramps.gen.const import GRAMPS_LOCALE as glocale
@@ -120,12 +128,6 @@ def __valid_options(self):
                                   "generate this report."), parent=self.window)
             return False
 
-        # other file output than PDF (PDF is only one supported right now)
-        if self.options.get_output()[-3:] != "pdf":
-            OkDialog(_("INFO"), _("This report only supports PDF as output "
-                                  "file format."), parent=self.window)
-            return False
-
         # if everything is valid
         return True
 
@@ -146,7 +148,10 @@ def write_report(self):
 
         # Heading
         if dct["head"] != "" or dct["head"] is not None:
-            self.write_heading(self._opt["head"])
+            self.doc.start_paragraph("MMR-Title")
+            mark = IndexMark(self._opt["head"], INDEX_TYPE_TOC, 1)
+            self.doc.write_text(self._opt["head"], mark)
+            self.doc.end_paragraph()
 
         # Media File
         self.write_media(path)
@@ -171,34 +176,29 @@ def write_report(self):
         if dct["incl_pers"]:
             self.write_person_reference(media)
 
+        self.doc.start_paragraph("MMR-Footer")
+        footer = self.menu.get_option_by_name('footer').get_value()
+        self.doc.write_text(footer)
+        self.doc.end_paragraph()
+
+
     def __write_media_notes(self, handles):
-        self.write_heading("Notes:", "Heading2")
+        self.write_heading("Notes:")
         for handle in handles:
             note = self._db.get_note_from_handle(handle)
             self.doc.write_styled_note(note.get_styledtext(),
-                                       note.get_format(), 'Default')
+                                       note.get_format(), "MMR-Details")
 
     def __write_media_tags(self, handles):
-        self.doc.start_table('Tags', 'tbl3')
-        self.doc.start_row()
-        self.doc.start_cell('cell')
-        self.write_heading("Tags:", "Heading2")
-        self.doc.end_cell()
-        self.doc.end_row()
+        self.write_heading("Tags:")
         for handle in handles:
             tag = self._db.get_tag_from_handle(handle)
-            self.doc.start_row()
-            self.doc.start_cell('cell')
-            self.doc.start_paragraph("Default")
+            self.doc.start_paragraph("MMR-Details")
             self.doc.write_text(tag.get_name())
             self.doc.end_paragraph()
-            self.doc.end_cell()
-            self.doc.end_row()
-        self.doc.end_table()
 
     def __write_media_citations(self, handles):
-        self.write_heading("Citations:", "Heading2")
-        self.doc.start_table('Tags', 'tbl3')
+        self.write_heading("Citations:")
         for handle in handles:
             cit = self._db.get_citation_from_handle(handle)
             for entry in cit.get_referenced_handles():
@@ -215,50 +215,24 @@ def __write_media_citations(self, handles):
                     txt += "%s, " % source.get_publication_info()
                 if cit.get_page():
                     txt += cit.get_page()
-            self.doc.start_row()
-            self.doc.start_cell('cell')
-            self.doc.start_paragraph("Default")
+            self.doc.start_paragraph("MMR-Details")
             self.doc.write_text(txt)
             self.doc.end_paragraph()
-            self.doc.end_cell()
-            self.doc.end_row()
-        self.doc.end_table()
 
     def __write_general_data(self, media):
         # General info
-        self.write_heading(_("General:"), "Heading2")
-        self.doc.start_table('General', 'tbl2')
-        self.doc.start_row()
+        self.write_heading("General:")
 
-        self.doc.start_cell('cell')
-        self.doc.start_paragraph("Default")
-        self.doc.write_text(_("Description:"))
-        self.doc.end_paragraph()
-        self.doc.end_cell()
 
-        self.doc.start_cell('cell')
-        self.doc.start_paragraph("Default")
+        self.doc.start_paragraph("MMR-Details")
+        self.doc.write_text("Description: ")
         self.doc.write_text(media.get_description())
         self.doc.end_paragraph()
-        self.doc.end_cell()
-
-        self.doc.end_row()
-        self.doc.start_row()
 
-        self.doc.start_cell('cell')
-        self.doc.start_paragraph("Default")
-        self.doc.write_text(_("Image type:"))
-        self.doc.end_paragraph()
-        self.doc.end_cell()
-
-        self.doc.start_cell('cell')
-        self.doc.start_paragraph("Default")
+        self.doc.start_paragraph("MMR-Details")
+        self.doc.write_text("Image type: ")
         self.doc.write_text(media.get_mime_type())
         self.doc.end_paragraph()
-        self.doc.end_cell()
-
-        self.doc.end_row()
-        self.doc.end_table()
 
     def __get_ref_list(self, media):
         dct = dict()
@@ -272,23 +246,15 @@ def __get_ref_list(self, media):
 
     def __write_media_attributes(self, media):
         if media.get_attribute_list():
-            self.write_heading("Attributes:", "Heading2")
-            self.doc.start_table('Tags', 'tbl2')
+            self.write_heading("Attributes:")
             for attr in media.get_attribute_list():
-                self.doc.start_row()
-                self.doc.start_cell('cell')
-                self.doc.start_paragraph("Default")
+                self.doc.start_paragraph("MMR-Details")
                 self.doc.write_text(attr.get_type().type2base())
-                self.doc.end_paragraph()
-                self.doc.end_cell()
-
-                self.doc.start_cell('cell')
-                self.doc.start_paragraph("Default")
+#                self.doc.end_paragraph()
+                self.doc.write_text(": ")
+#                self.doc.start_paragraph("MMR-Details")
                 self.doc.write_text(attr.get_value())
                 self.doc.end_paragraph()
-                self.doc.end_cell()
-                self.doc.end_row()
-            self.doc.end_table()
 
     def pers_ref_lst(self, media_handle):
         """
@@ -317,9 +283,9 @@ def pers_ref_lst(self, media_handle):
                             lst.append((person, rect))
         return lst
 
-    def write_heading(self, txt, heading="Heading"):
+    def write_heading(self, txt):
         """Write a report heading"""
-        self.doc.start_paragraph(heading)
+        self.doc.start_paragraph("MMR-Heading")
         self.doc.write_text(txt)
         self.doc.end_paragraph()
 
@@ -338,6 +304,8 @@ def write_media(self, path):
                            self._opt["media_h"] * 0.009)
             # height is capped to 90% to save some space for report heading
             self.doc.add_media(self.filename, 'center', width, height)
+            self.doc.page_break()
+            self.write_heading(self.filename)
         else:
             no_file = _('File does not exist')
             self.user.warn(_("Could not add photo to page"),
@@ -351,11 +319,10 @@ def write_person_reference(self, media):
         :param media: the media object used in this report
         :type media: :class Media: object
         """
-        # Add some space by adding empty heading
-        self.write_heading(" ")
         # Add person references
         handle = media.serialize()[0]
         ref_lst = self.pers_ref_lst(handle)
+        self.write_heading('Referenced Persons')
         self.doc.start_table('Referenced Persons', 'tbl')
         for i in range((len(ref_lst)//2)):
             ref1 = ref_lst[2*i]
@@ -364,22 +331,22 @@ def write_person_reference(self, media):
             pers_name2 = name_displayer.display(ref2[0])
 
             self.doc.start_row()
-            self.doc.start_cell('cell')
+            self.doc.start_cell("cell")
             self.doc.add_media(self.filename, 'center', 2.0, 2.0, crop=ref1[1])
             self.doc.end_cell()
 
-            self.doc.start_cell('cell')
-            self.doc.start_paragraph("Default")
+            self.doc.start_cell("cell")
+            self.doc.start_paragraph("MMR-Details")
             self.doc.write_text(pers_name1)
             self.doc.end_paragraph()
             self.doc.end_cell()
 
-            self.doc.start_cell('cell')
+            self.doc.start_cell("cell")
             self.doc.add_media(self.filename, 'center', 2.0, 2.0, crop=ref2[1])
             self.doc.end_cell()
 
-            self.doc.start_cell('cell')
-            self.doc.start_paragraph("Default")
+            self.doc.start_cell("cell")
+            self.doc.start_paragraph("MMR-Details")
             self.doc.write_text(pers_name2)
             self.doc.end_paragraph()
             self.doc.end_cell()
@@ -387,13 +354,13 @@ def write_person_reference(self, media):
         if len(ref_lst) % 2 != 0:
             pers_name = name_displayer.display(ref_lst[-1][0])
             self.doc.start_row()
-            self.doc.start_cell('cell')
+            self.doc.start_cell("cell")
             self.doc.add_media(self.filename, 'center', 2.0, 2.0,
                                crop=ref_lst[-1][1])
             self.doc.end_cell()
 
-            self.doc.start_cell('cell')
-            self.doc.start_paragraph("Default")
+            self.doc.start_cell("cell")
+            self.doc.start_paragraph("MMR-Details")
             self.doc.write_text(pers_name)
             self.doc.end_paragraph()
             self.doc.end_cell()
@@ -402,13 +369,11 @@ def write_person_reference(self, media):
 
     def write_note(self):
         """Write a note, if included."""
-        # Add some space by adding empty heading
-        self.write_heading(" ")
 
         nid = self._opt["note"]  # note id
         note = self._db.get_note_from_gramps_id(nid)
         self.doc.write_styled_note(note.get_styledtext(), note.get_format(),
-                                   'Default')
+                                   'MMR-Details')
 
 
 # ----------------------------------------------------------------------------
@@ -457,6 +422,16 @@ def add_menu_options(self, menu):
                            "height."))
         menu.add_option(_("Report Options"), "media_h", media_h)
 
+        dateinfo = time.localtime(time.time())
+        rname = _("researcher name")
+
+        footer_string = _('Copyright %(year)d %(name)s') % {
+            'year' : dateinfo[0], 'name' : rname}
+        footer = StringOption(_('Footer'), footer_string)
+        footer.set_help(_("Footer string for the report."))
+        menu.add_option(_("Report Options"), "footer", footer)
+
+
     def __update_custom_note_opt(self):
         self.note.set_available(False)
         if self.incl_note.get_value():
@@ -465,25 +440,47 @@ def __update_custom_note_opt(self):
     def make_default_style(self, default_style):
         """Define the default styling."""
         para = ParagraphStyle()
-        default_style.add_paragraph_style("Default", para)
+        default_style.add_paragraph_style("default_style", para)
 
         font = FontStyle()
-        font.set(size=16, bold=1)
+        font.set(face=FONT_SANS_SERIF, size=18, bold=1)
+        para = ParagraphStyle()
         para.set_font(font)
         para.set_header_level(1)
         para.set_top_margin(0.25)
         para.set_bottom_margin(0.25)
         para.set_alignment(PARA_ALIGN_CENTER)
-        default_style.add_paragraph_style("Heading", para)
+        para.set_description(_('The style used for the title of the report.'))
+        default_style.add_paragraph_style("MMR-Title", para)
 
         font = FontStyle()
-        font.set(size=12, bold=1)
+        font.set(face=FONT_SANS_SERIF, size=10, bold=1)
+        para = ParagraphStyle()
         para.set_font(font)
-        para.set_alignment(PARA_ALIGN_LEFT)
-        default_style.add_paragraph_style("Heading2", para)
+        para.set_alignment(PARA_ALIGN_CENTER)
+        para.set_top_border(True)
+        para.set_top_margin(pt2cm(6))
+        para.set_description(_('The style used for the report footer.'))
+        default_style.add_paragraph_style("MMR-Footer", para)
 
-        cell = TableCellStyle()
-        default_style.add_cell_style("cell", cell)
+        font = FontStyle()
+        font.set(face=FONT_SERIF, size=12, italic=0, bold=1)
+        para = ParagraphStyle()
+        para.set_font(font)
+        para.set_header_level(2)
+        para.set(first_indent=0.0, lmargin=1.0)
+        para.set_top_margin(0.50)
+        para.set_bottom_margin(0.0)
+        para.set_description(_('The style used for headings.'))
+        default_style.add_paragraph_style("MMR-Heading", para)
+
+        font = FontStyle()
+        font.set(face=FONT_SERIF, size=10)
+        para = ParagraphStyle()
+        para.set_font(font)
+        para.set(first_indent=0.0, lmargin=1.0)
+        para.set_description(_('The style used for details.'))
+        default_style.add_paragraph_style("MMR-Details", para)
 
         tbl = TableStyle()
         tbl.set_width(100)
@@ -494,15 +491,5 @@ def make_default_style(self, default_style):
         tbl.set_column_width(3, 30)
         default_style.add_table_style('tbl', tbl)
 
-        tbl = TableStyle()
-        tbl.set_width(100)
-        tbl.set_columns(2)
-        tbl.set_column_width(0, 50)
-        tbl.set_column_width(1, 50)
-        default_style.add_table_style('tbl2', tbl)
-
-        tbl = TableStyle()
-        tbl.set_width(100)
-        tbl.set_columns(1)
-        tbl.set_column_width(0, 100)
-        default_style.add_table_style('tbl3', tbl)
+        cell = TableCellStyle()
+        default_style.add_cell_style("cell", cell)

From e386db3e823ca0c40dacc9dffba03ac02f7783d5 Mon Sep 17 00:00:00 2001
From: Mattkmmr <49940207+Mattkmmr@users.noreply.github.com>
Date: Wed, 22 Dec 2021 11:02:32 +0100
Subject: [PATCH 2/2] Refactoring

---
 MediaReport/media_report.gpr.py |  11 +-
 MediaReport/media_report.py     | 373 +++++++++++++-------------------
 2 files changed, 154 insertions(+), 230 deletions(-)

diff --git a/MediaReport/media_report.gpr.py b/MediaReport/media_report.gpr.py
index 51d2193d2..55cbe67a3 100644
--- a/MediaReport/media_report.gpr.py
+++ b/MediaReport/media_report.gpr.py
@@ -1,7 +1,8 @@
 #
 # Gramps - a GTK+/GNOME based genealogy program
 #
-# Copyright (C) 2019  Matthias Kemmer <matt.familienforschung@gmail.com>
+# Copyright (C) 2019-2021 Matthias Kemmer
+# Copyright (C) 2021 George Baynes
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -23,14 +24,14 @@
          name = _("Media Report"),
          description = _("Generates report including images, image data"
                          " and notes."),
-         version = '1.1.7',
+         version = '1.2.0',
          gramps_target_version = "5.1",
          status = STABLE,
          fname = "media_report.py",
-         authors = ["Matthias Kemmer"],
-         authors_email = ["matt.familienforschung@gmail.com"],
+         authors = ["Matthias Kemmer", "George Baynes"],
+         authors_email = ["matt.familienforschung@gmail.com", "baynes@ntlworld.com"],
          category = CATEGORY_TEXT,
          reportclass = 'MediaReport',
          optionclass = 'ReportOptions',
-         report_modes = [REPORT_MODE_CLI, REPORT_MODE_GUI],
+         report_modes = [REPORT_MODE_GUI],
          )
diff --git a/MediaReport/media_report.py b/MediaReport/media_report.py
index cc5ba8ce7..d6ab08a87 100644
--- a/MediaReport/media_report.py
+++ b/MediaReport/media_report.py
@@ -1,7 +1,8 @@
 #
 # Gramps - a GTK+/GNOME based genealogy program
 #
-# Copyright (C) 2019 Matthias Kemmer
+# Copyright (C) 2019-2021 Matthias Kemmer
+# Copyright (C) 2021 George Baynes
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -17,12 +18,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 #
-"""
-1.0 Matthias Kemmer
-1.1 George Baynes (baynes@ntlworld.com) adapted to give .odt .ps output
-    it still fails .rtf .txt .html and print due to attempt to find available
-    width or height. Unable to check latex output.
-"""
+"""Create a Media Report containing images, image data and notes."""
+
 
 # ----------------------------------------------------------------------------
 #
@@ -30,7 +27,6 @@
 #
 # ----------------------------------------------------------------------------
 import os
-import time
 from math import floor
 
 # ----------------------------------------------------------------------------
@@ -42,24 +38,18 @@
 from gramps.gen.utils.file import media_path_full
 from gramps.gen.plug.report import Report, MenuReportOptions
 from gramps.gen.display.name import displayer as name_displayer
-from gramps.gen.plug.menu import (MediaOption, NoteOption, BooleanOption,
-                                  StringOption, NumberOption)
-from gramps.gen.plug.docgen import (ParagraphStyle, FontStyle, PARA_ALIGN_CENTER,
-                                    IndexMark, FONT_SERIF,
-                                    FONT_SANS_SERIF, INDEX_TYPE_TOC, TableStyle,
-                                    TableCellStyle)
-from gramps.gen.plug.report.utils import pt2cm
-
-# Old:
-#from gramps.gen.const import GRAMPS_LOCALE as glocale
-#_ = glocale.translation.gettext
-
-# New:
-#------------------------------------------------------------------------
+from gramps.gen.plug.menu import (
+    MediaOption, NoteOption, BooleanOption, StringOption, NumberOption)
+from gramps.gen.plug.docgen import (
+    ParagraphStyle, FontStyle, PARA_ALIGN_CENTER, IndexMark, FONT_SERIF,
+    FONT_SANS_SERIF, INDEX_TYPE_TOC, TableStyle, TableCellStyle)
+
+
+# ------------------------------------------------------------------------
 #
 # Internationalisation
 #
-#------------------------------------------------------------------------
+# ------------------------------------------------------------------------
 from gramps.gen.const import GRAMPS_LOCALE as glocale
 try:
     _trans = glocale.get_addon_translator(__file__)
@@ -67,6 +57,7 @@
     _trans = glocale.translation
 _ = _trans.gettext
 
+
 # ----------------------------------------------------------------------------
 #
 # Media Report
@@ -74,94 +65,43 @@
 # ----------------------------------------------------------------------------
 class MediaReport(Report):
     """Create a Media Report containing images, image data and notes."""
+
     def __init__(self, database, options, user):
         Report.__init__(self, database, options, user)
 
         self.menu = options.menu
-        self.options = options
-        self._db = self.database
-        self._opt = self.get_opt_dict()
+        self.db = self.database
+        self.opt = options.options_dict
         self.user = user
         self.window = self.user.uistate.window
         self.filename = None
 
-    def get_opt_dict(self):
-        """
-        Get the values of the menu options
-        :return: dictionary e.g. {opt_name:value}
-        """
-        dct = dict()
-        for name in self.menu.get_all_option_names():
-            opt = self.menu.get_option_by_name(name)
-            dct[name] = opt.get_value()
-        return dct
-
-    def __media_is_img(self, mid):
-        if mid != "":
-            media = self._db.get_media_from_gramps_id(mid)
-            media_type = media.get_mime_type()
-            return "image" in media_type
-        return False
-
-    def __valid_options(self):
-        """Check if all menu options are valid for report generation."""
-        dct = self._opt
-        mid = dct["mid"]
-        is_img = self.__media_is_img(mid)
-
-        # no media file selected
-        if not mid or mid == "":
-            OkDialog(_("INFO"), _("You have to select an image to generate "
-                                  "this report."), parent=self.window)
-            return False
-
-        # 'include custom note' checked, but no custom note selected
-        if dct["incl_note"] and dct["note"] == "":
-            OkDialog(_("INFO"), _("You have to select a custom note or uncheck"
-                                  " the option 'include custom note' to "
-                                  "generate this report."), parent=self.window)
-            return False
-
-        # incorrect media file, not an image
-        if not is_img:
-            OkDialog(_("INFO"), _("You have to select an image to "
-                                  "generate this report."), parent=self.window)
-            return False
-
-        # if everything is valid
-        return True
-
     def write_report(self):
-        """
-        Inherited method; called by Report() in _ReportDialog.py
-        """
-        # check if an image is selected and a note, if include note is checked
-        # stop report generation if one is missing
+        """Report generation."""
+
         if not self.__valid_options():
-            print("Invalid options. Stop report generation.")
-            return
+            return False
 
-        dct = self._opt
-        mid = dct["mid"]
-        media = self._db.get_media_from_gramps_id(mid)
+        mid = self.opt["mid"]
+        media = self.db.get_media_from_gramps_id(mid)
         path = media.get_text_data_list()[0]
 
         # Heading
-        if dct["head"] != "" or dct["head"] is not None:
+        if self.opt["head"] != "" or self.opt["head"] is not None:
             self.doc.start_paragraph("MMR-Title")
-            mark = IndexMark(self._opt["head"], INDEX_TYPE_TOC, 1)
-            self.doc.write_text(self._opt["head"], mark)
+            mark = IndexMark(self.opt["head"], INDEX_TYPE_TOC, 1)
+            self.doc.write_text(self.opt["head"], mark)
             self.doc.end_paragraph()
 
         # Media File
-        self.write_media(path)
+        self.__write_media(path)
 
         # Custom Note
-        if self._opt["incl_note"]:
-            self.write_note()
+        if self.opt["incl_note"]:
+            self.__write_note()
 
         # Add all media data
-        if dct["incl_data"]:
+        if self.opt["incl_data"]:
             self.__write_general_data(media)
             self.__write_media_attributes(media)
             ref_dct = self.__get_ref_list(media)
@@ -173,40 +113,82 @@ def write_report(self):
                 self.__write_media_citations(ref_dct["Citation"])
 
         # Person references
-        if dct["incl_pers"]:
-            self.write_person_reference(media)
+        if self.opt["incl_pers"]:
+            self.__write_person_reference(media)
 
-        self.doc.start_paragraph("MMR-Footer")
-        footer = self.menu.get_option_by_name('footer').get_value()
-        self.doc.write_text(footer)
-        self.doc.end_paragraph()
+    def __is_image(self, mid):
+        if mid == "":
+            return False
+        media = self.db.get_media_from_gramps_id(mid)
+        if not media:
+            return False
+        media_type = media.get_mime_type()
+        return "image" in media_type
+
+    def __valid_options(self):
+        # Check if all report options are valid:
+        # 1. A media file is selected
+        # 2. Media file is an image
+        # 3. A note is selected (if note option is checked)
+        include_note = self.opt["incl_note"]
+        note = self.opt["note"]
+        mid = self.opt["mid"]
+
+        # no media file selected
+        if self.window and (not mid or mid == ""):
+            OkDialog(
+                _("INFO"),
+                _("You have to select an image to generate this report."),
+                parent=self.window)
+            return False
+
+        # 'include custom note' checked, but no custom note selected
+        if self.window and include_note and note == "":
+            OkDialog(
+                _("INFO"),
+                _("You have to select a custom note or uncheck"
+                  " the option 'include custom note' to "
+                  "generate this report."),
+                parent=self.window)
+            return False
 
+        # incorrect media file, not an image
+        if self.window and not self.__is_image(mid):
+            OkDialog(
+                _("INFO"),
+                _("You have to select an image to generate this report."),
+                parent=self.window)
+            return False
+
+        # if everything is valid
+        return True
 
     def __write_media_notes(self, handles):
-        self.write_heading("Notes:")
+        self.__write_heading("Notes:")
         for handle in handles:
-            note = self._db.get_note_from_handle(handle)
-            self.doc.write_styled_note(note.get_styledtext(),
-                                       note.get_format(), "MMR-Details")
+            note = self.db.get_note_from_handle(handle)
+            self.doc.write_styled_note(
+                note.get_styledtext(), note.get_format(), "MMR-Details")
 
     def __write_media_tags(self, handles):
-        self.write_heading("Tags:")
+        self.__write_heading("Tags:")
         for handle in handles:
-            tag = self._db.get_tag_from_handle(handle)
+            tag = self.db.get_tag_from_handle(handle)
             self.doc.start_paragraph("MMR-Details")
             self.doc.write_text(tag.get_name())
             self.doc.end_paragraph()
 
     def __write_media_citations(self, handles):
-        self.write_heading("Citations:")
+        self.__write_heading("Citations:")
         for handle in handles:
-            cit = self._db.get_citation_from_handle(handle)
+            cit = self.db.get_citation_from_handle(handle)
+            src_handle = ""
+            txt = ""
             for entry in cit.get_referenced_handles():
                 if entry[0] == "Source":
                     src_handle = entry[1]
-            if src_handle:
-                source = self._db.get_source_from_handle(src_handle)
-                txt = ""
+            if src_handle != "":
+                source = self.db.get_source_from_handle(src_handle)
                 if source.get_author():
                     txt += "%s: " % source.get_author()
                 if source.get_title():
@@ -220,9 +202,7 @@ def __write_media_citations(self, handles):
             self.doc.end_paragraph()
 
     def __write_general_data(self, media):
-        # General info
-        self.write_heading("General:")
-
+        self.__write_heading("General:")
 
         self.doc.start_paragraph("MMR-Details")
         self.doc.write_text("Description: ")
@@ -246,134 +226,95 @@ def __get_ref_list(self, media):
 
     def __write_media_attributes(self, media):
         if media.get_attribute_list():
-            self.write_heading("Attributes:")
+            self.__write_heading("Attributes:")
             for attr in media.get_attribute_list():
                 self.doc.start_paragraph("MMR-Details")
                 self.doc.write_text(attr.get_type().type2base())
-#                self.doc.end_paragraph()
                 self.doc.write_text(": ")
-#                self.doc.start_paragraph("MMR-Details")
                 self.doc.write_text(attr.get_value())
                 self.doc.end_paragraph()
 
-    def pers_ref_lst(self, media_handle):
-        """
-        Get a person reference list with image rectangle information.
-
-        :param media_handle: handle of the media file
-        :type media_handle: string
-        :return lst: list of reference tuples
-        :rtype lst: list
-        :example lst: (:class Person: object, (0, 0, 100, 100))
-        """
+    def __get_pers_ref_lst(self, media_handle):
         lst = list()
-        backrefs = self._db.find_backlink_handles(media_handle)
+        backrefs = self.db.find_backlink_handles(media_handle)
         for (reftype, ref) in backrefs:
-            if reftype == "Person":
-                person = self._db.get_person_from_handle(ref)
-                gallery = person.get_media_list()
-                for mediaref in gallery:
-                    referenced_handles = mediaref.get_referenced_handles()
-                    if len(referenced_handles) == 1:
-                        handle_type, handle = referenced_handles[0]
-                        if handle_type == "Media" and handle == media_handle:
-                            rect = mediaref.get_rectangle()
-                            if rect is None:
-                                rect = (0, 0, 100, 100)
-                            lst.append((person, rect))
-        return lst
-
-    def write_heading(self, txt):
-        """Write a report heading"""
+            if reftype != "Person":
+                continue
+            person = self.db.get_person_from_handle(ref)
+            if not person:
+                continue
+            gallery = person.get_media_list()
+            if not gallery:
+                continue
+            for mediaref in gallery:
+                referenced_handles = mediaref.get_referenced_handles()
+                if not referenced_handles:
+                    continue
+                handle_type, handle = referenced_handles[0]
+                if handle_type == "Media" and handle == media_handle:
+                    rect = mediaref.get_rectangle()
+                    if not rect:
+                        rect = (0, 0, 100, 100)
+                    lst.append((person, rect))
+        return lst  # [(class:Person, (0, 0, 100, 100))]
+
+    def __write_heading(self, txt):
         self.doc.start_paragraph("MMR-Heading")
         self.doc.write_text(txt)
         self.doc.end_paragraph()
 
-    def write_media(self, path):
-        """
-        Add the image to the report
-
-        :param path: gramps media path
-        :type path: string
-        """
-        self.filename = media_path_full(self._db, path)
+    def __write_media(self, path):
+        self.filename = media_path_full(self.db, path)
         if os.path.exists(self.filename):
-            width = floor(self.doc.get_usable_width() *
-                          self._opt["media_w"] * 0.01)
-            height = floor(self.doc.get_usable_height() *
-                           self._opt["media_h"] * 0.009)
-            # height is capped to 90% to save some space for report heading
-            self.doc.add_media(self.filename, 'center', width, height)
+            try:
+                width = floor(self.doc.get_usable_width() *
+                              self.opt["media_w"] * 0.01)
+                height = floor(self.doc.get_usable_height() *
+                               self.opt["media_h"] * 0.009)
+                # height is capped to 90% to save some space for report heading
+                self.doc.add_media(self.filename, 'center', width, height)
+            except AttributeError:
+                # AttributeError, because some docgens don't support the
+                # methods 'get_usable_width' and 'get_usable_height'
+                self.doc.add_media(self.filename, 'center', 1.0, 1.0)
             self.doc.page_break()
-            self.write_heading(self.filename)
         else:
             no_file = _('File does not exist')
             self.user.warn(_("Could not add photo to page"),
                            _("%(str1)s: %(str2)s") % {'str1': self.filename,
                                                       'str2': no_file})
 
-    def write_person_reference(self, media):
-        """
-        Add a table that list all referenced people in the image
-
-        :param media: the media object used in this report
-        :type media: :class Media: object
-        """
-        # Add person references
+    def __write_person_reference(self, media):
         handle = media.serialize()[0]
-        ref_lst = self.pers_ref_lst(handle)
-        self.write_heading('Referenced Persons')
+        ref_lst = self.__get_pers_ref_lst(handle)
+        self.__write_heading('Referenced Persons')
         self.doc.start_table('Referenced Persons', 'tbl')
-        for i in range((len(ref_lst)//2)):
-            ref1 = ref_lst[2*i]
-            ref2 = ref_lst[2*i + 1]
-            pers_name1 = name_displayer.display(ref1[0])
-            pers_name2 = name_displayer.display(ref2[0])
-
-            self.doc.start_row()
-            self.doc.start_cell("cell")
-            self.doc.add_media(self.filename, 'center', 2.0, 2.0, crop=ref1[1])
-            self.doc.end_cell()
-
-            self.doc.start_cell("cell")
-            self.doc.start_paragraph("MMR-Details")
-            self.doc.write_text(pers_name1)
-            self.doc.end_paragraph()
-            self.doc.end_cell()
+        new_row = True
+        for entry in ref_lst:
+            name = name_displayer.display(entry[0])
+            border = entry[1]
 
+            if new_row:
+                self.doc.start_row()
             self.doc.start_cell("cell")
-            self.doc.add_media(self.filename, 'center', 2.0, 2.0, crop=ref2[1])
+            self.doc.add_media(self.filename, 'center', 2.0, 2.0, crop=border)
             self.doc.end_cell()
 
             self.doc.start_cell("cell")
             self.doc.start_paragraph("MMR-Details")
-            self.doc.write_text(pers_name2)
+            self.doc.write_text(name)
             self.doc.end_paragraph()
             self.doc.end_cell()
-            self.doc.end_row()
-        if len(ref_lst) % 2 != 0:
-            pers_name = name_displayer.display(ref_lst[-1][0])
-            self.doc.start_row()
-            self.doc.start_cell("cell")
-            self.doc.add_media(self.filename, 'center', 2.0, 2.0,
-                               crop=ref_lst[-1][1])
-            self.doc.end_cell()
-
-            self.doc.start_cell("cell")
-            self.doc.start_paragraph("MMR-Details")
-            self.doc.write_text(pers_name)
-            self.doc.end_paragraph()
-            self.doc.end_cell()
-            self.doc.end_row()
+            if not new_row:
+                self.doc.end_row()
+            new_row = not new_row
         self.doc.end_table()
 
-    def write_note(self):
-        """Write a note, if included."""
-
-        nid = self._opt["note"]  # note id
-        note = self._db.get_note_from_gramps_id(nid)
-        self.doc.write_styled_note(note.get_styledtext(), note.get_format(),
-                                   'MMR-Details')
+    def __write_note(self):
+        nid = self.opt["note"]  # note id
+        note = self.db.get_note_from_gramps_id(nid)
+        self.doc.write_styled_note(
+            note.get_styledtext(), note.get_format(), 'MMR-Details')
 
 
 # ----------------------------------------------------------------------------
@@ -383,11 +324,12 @@ def write_note(self):
 # ----------------------------------------------------------------------------
 class ReportOptions(MenuReportOptions):
     """Report options for Media Report"""
+
     def __init__(self, name, dbase):
         MenuReportOptions.__init__(self, name, dbase)
 
     def add_menu_options(self, menu):
-        """Add the options to the report option menu"""
+        """Add the options to the report option menu."""
         head = StringOption(_("Heading"), "")
         menu.add_option(_("Report Options"), "head", head)
 
@@ -422,16 +364,6 @@ def add_menu_options(self, menu):
                            "height."))
         menu.add_option(_("Report Options"), "media_h", media_h)
 
-        dateinfo = time.localtime(time.time())
-        rname = _("researcher name")
-
-        footer_string = _('Copyright %(year)d %(name)s') % {
-            'year' : dateinfo[0], 'name' : rname}
-        footer = StringOption(_('Footer'), footer_string)
-        footer.set_help(_("Footer string for the report."))
-        menu.add_option(_("Report Options"), "footer", footer)
-
-
     def __update_custom_note_opt(self):
         self.note.set_available(False)
         if self.incl_note.get_value():
@@ -453,16 +385,6 @@ def make_default_style(self, default_style):
         para.set_description(_('The style used for the title of the report.'))
         default_style.add_paragraph_style("MMR-Title", para)
 
-        font = FontStyle()
-        font.set(face=FONT_SANS_SERIF, size=10, bold=1)
-        para = ParagraphStyle()
-        para.set_font(font)
-        para.set_alignment(PARA_ALIGN_CENTER)
-        para.set_top_border(True)
-        para.set_top_margin(pt2cm(6))
-        para.set_description(_('The style used for the report footer.'))
-        default_style.add_paragraph_style("MMR-Footer", para)
-
         font = FontStyle()
         font.set(face=FONT_SERIF, size=12, italic=0, bold=1)
         para = ParagraphStyle()
@@ -492,4 +414,5 @@ def make_default_style(self, default_style):
         default_style.add_table_style('tbl', tbl)
 
         cell = TableCellStyle()
+        cell.set_padding(0.2)
         default_style.add_cell_style("cell", cell)