Repository: dkratzert/FinalCif (language: python)

Issue:
Save a diff to the original CIF
FinalCif should save a diff to the original CIF in the work directory in order to keep the changes made by the user.
How to select which changes to keep? We don't want to keep atom parameters for example.
* Probably only changes edited by templates?
* Or should I add checkbox to the text temlates where you can activate "keep this thing"?


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 24268041..59e277f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -209,3 +209,6 @@ docs
 finalcif/gui/finalcif_gui.ui.autosave
 test-data/1000007-multi-finalcif.cif
 test.docx
+tests/examples/work/cu_BruecknerJK_153F40_0m-finalcif_changes.cif
+tests/examples/work/platon.out
+test-data/DK_Zucker2_0m-finalcif_changes.cif
diff --git a/finalcif/appwindow.py b/finalcif/appwindow.py
index 7f1807a9..d68d2000 100644
--- a/finalcif/appwindow.py
+++ b/finalcif/appwindow.py
@@ -12,14 +12,14 @@
 from datetime import datetime
 from math import sin, radians
 from pathlib import Path, WindowsPath
-from typing import Union, Dict, Tuple, List
+from typing import Union, Dict, Tuple, List, Optional
 
 import gemmi.cif
 import qtawesome as qta
 import requests
 from PyQt5 import QtCore, QtGui, QtWebEngineWidgets
 from PyQt5.QtCore import QThread, QTimer, Qt
-from PyQt5.QtWidgets import QMainWindow, QHeaderView, QShortcut, QCheckBox, QListWidgetItem, QApplication, \
+from PyQt5.QtWidgets import QMainWindow, QShortcut, QCheckBox, QListWidgetItem, QApplication, \
     QPlainTextEdit, QFileDialog
 from gemmi import cif
 from qtpy.QtGui import QDesktopServices
@@ -36,8 +36,8 @@
 from finalcif.equip_property.equipment import Equipment
 from finalcif.equip_property.properties import Properties
 from finalcif.equip_property.tools import read_document_from_cif_file
-from finalcif.gui.custom_classes import COL_CIF, COL_DATA, COL_EDIT, MyTableWidgetItem, light_green, yellow, MyCifTable, \
-    light_blue, white
+from finalcif.gui.custom_classes import COL_CIF, COL_DATA, COL_EDIT, MyTableWidgetItem, light_green, yellow, light_blue, \
+    white
 from finalcif.gui.dialogs import show_update_warning, unable_to_open_message, show_general_warning, \
     cif_file_open_dialog, \
     bad_z_message, show_res_checksum_warning, show_hkl_checksum_warning, cif_file_save_dialog
@@ -54,7 +54,8 @@
 from finalcif.tools.dsrmath import my_isnumeric
 from finalcif.tools.misc import next_path, do_not_import_keys, celltxt, to_float, \
     combobox_fields, \
-    do_not_import_from_stoe_cfx, cif_to_header_label, grouper, is_database_number, file_age_in_days, open_file
+    do_not_import_from_stoe_cfx, cif_to_header_label, grouper, is_database_number, file_age_in_days, open_file, \
+    strip_finalcif_of_name
 from finalcif.tools.options import Options
 from finalcif.tools.platon import Platon
 from finalcif.tools.settings import FinalCifSettings
@@ -103,7 +104,7 @@ def __init__(self, file=None, unit_test: bool = False):
         self.ui.cif_main_table.installEventFilter(self)
         # Sorting desynchronized header and columns:
         self.ui.cif_main_table.setSortingEnabled(False)
-        self.distribute_cif_main_table_columns_evenly()
+        self.ui.cif_main_table.distribute_cif_main_table_columns_evenly()
         # Make sure the start page is shown and not the edit page:
         self.ui.CheckCIFResultsTabWidget.setCurrentIndex(0)
         self.ui.TemplatesStackedWidget.setCurrentIndex(0)
@@ -128,14 +129,6 @@ def __init__(self, file=None, unit_test: bool = False):
         self.make_button_icons()
         self.format_report_button()
 
-    def distribute_cif_main_table_columns_evenly(self) -> None:
-        hheader = self.ui.cif_main_table.horizontalHeader()
-        hheader.setSectionResizeMode(COL_CIF, QHeaderView.Stretch)
-        hheader.setSectionResizeMode(COL_DATA, QHeaderView.Stretch)
-        hheader.setSectionResizeMode(COL_EDIT, QHeaderView.Stretch)
-        hheader.setAlternatingRowColors(True)
-        self.ui.cif_main_table.verticalHeader().setAlternatingRowColors(True)
-
     def set_initial_button_states(self) -> None:
         self.ui.appendCifPushButton.setDisabled(True)
         self.ui.PictureWidthDoubleSpinBox.setRange(0.0, 25)
@@ -143,19 +136,44 @@ def set_initial_button_states(self) -> None:
         # Just too slow for large structures:
         self.ui.growCheckBox.setChecked(False)
         self.ui.CheckcifButton.setDisabled(True)
+        self.ui.CheckcifStartButton.setDisabled(True)
+        self.ui.ReportPicPushButton.setDisabled(True)
+        self.ui.SaveFullReportButton.setDisabled(True)
         self.ui.CheckcifHTMLOnlineButton.setDisabled(True)
         self.ui.CheckcifPDFOnlineButton.setDisabled(True)
         self.ui.SaveCifButton.setDisabled(True)
         self.ui.ExploreDirButton.setDisabled(True)
         self.ui.DetailsPushButton.setDisabled(True)
         self.ui.SourcesPushButton.setDisabled(True)
-        self.ui.OptionsPushButton.setDisabled(True)
+        self.ui.OptionsPushButton.setEnabled(True)
         self.ui.ImportCifPushButton.setDisabled(True)
         self.ui.CODpushButton.setDisabled(True)
         self.ui.CCDCpushButton.setDisabled(True)
         self.ui.ShredCifButton.setDisabled(True)
         self.ui.LoopsPushButton.setDisabled(True)
 
+    def enable_buttons(self):
+        self.ui.appendCifPushButton.setEnabled(True)
+        self.ui.CheckcifButton.setEnabled(True)
+        self.ui.CheckcifStartButton.setEnabled(True)
+        self.ui.ReportPicPushButton.setEnabled(True)
+        self.ui.SaveFullReportButton.setEnabled(True)
+        self.ui.CheckcifHTMLOnlineButton.setEnabled(True)
+        self.ui.CheckcifPDFOnlineButton.setEnabled(True)
+        self.ui.SaveCifButton.setEnabled(True)
+        self.ui.ExploreDirButton.setEnabled(True)
+        self.ui.DetailsPushButton.setEnabled(True)
+        self.ui.SourcesPushButton.setEnabled(True)
+        self.ui.OptionsPushButton.setEnabled(True)
+        self.ui.ImportCifPushButton.setEnabled(True)
+        self.ui.CODpushButton.setEnabled(True)
+        self.ui.CCDCpushButton.setEnabled(True)
+        self.ui.LoopsPushButton.setEnabled(True)
+        if self.cif.is_multi_cif:
+            self.ui.CODpushButton.setDisabled(True)
+        else:
+            self.ui.CODpushButton.setEnabled(True)
+
     def format_report_button(self):
         if self.report_without_template():
             self.ui.SaveFullReportButton.setText('Make Report')
@@ -297,6 +315,10 @@ def connect_signals_and_slots(self) -> None:
         self.ui.ExportAllTemplatesPushButton.clicked.connect(self.export_all_templates)
         self.ui.ImportAllTemplatesPushButton.clicked.connect(self.import_all_templates)
 
+    @property
+    def finalcif_changes_filename(self):
+        return self.cif.finalcif_file_prefixed(prefix='', suffix='-finalcif_changes.cif', force_strip=True)
+
     def export_all_templates(self, filename: Path = None):
         import pickle
         if not filename:
@@ -470,10 +492,13 @@ def check_if_file_field_contains_database_number(self):
             else:
                 self.ui.SelectCif_LineEdit.setText('')
 
+    @property
+    def current_block(self) -> int:
+        return self.ui.datanameComboBox.currentIndex()
+
     def open_cod_page(self):
-        current_block = self.ui.datanameComboBox.currentIndex()
         self.save_current_cif_file()
-        self.load_cif_file(self.cif.finalcif_file, current_block)
+        self.load_cif_file(self.cif.finalcif_file, self.current_block)
         self.deposit.cif = self.cif
         self.ui.MainStackedWidget.setCurrentIndex(7)
 
@@ -525,16 +550,13 @@ def _ccdc_deposit(self) -> None:
 
     def _deleted_row(self, key: str) -> None:
         """
-        Deletes a row of the main table and reloads the cif file.
+        Deletes a row of the main table.
         """
-        current_block = self.ui.datanameComboBox.currentIndex()
-        if self.cif.block.find_pair(key):
-            self.cif.block.find([key]).erase()
-            if key in self.missing_data:
-                self.missing_data.discard(key)
-                # del self.missing_data[self.missing_data.index(key)]
-            self.save_current_cif_file()
-            self.load_cif_file(self.cif.finalcif_file, block=current_block)
+        del self.cif[key]
+        if self.options.track_changes:
+            changes_cif = self.get_changes_cif(self.finalcif_changes_filename)
+            del changes_cif[key]
+            changes_cif.save(self.finalcif_changes_filename)
 
     def check_for_update_version(self) -> None:
         if os.environ.get('NO_NETWORK'):
@@ -884,7 +906,6 @@ def do_offline_checkcif(self) -> None:
             p = Platon(self.cif.fileobj.resolve(), timeout, '-u')
         except Exception as e:
             print(e)
-            # self.ui.CheckcifButton.setDisabled(True)
             return
         checkcif_out = self.ui.CheckcifPlaintextEdit
         checkcif_out.setPlainText('Platon output: \nThis might not be the same as the IUCr CheckCIF!')
@@ -1113,10 +1134,7 @@ def save_current_cif_file(self) -> Union[bool, None]:
             # No file is opened
             return None
         self.cif.rename_data_name(''.join(self.ui.datanameComboBox.currentText().split(' ')))
-        # restore header, otherwise item is not saved:
-        table = self.ui.cif_main_table
-        table.setCurrentItem(None)  # makes sure also the currently edited item is saved
-        self.store_data_from_table_rows(table)
+        self.store_data_from_table_rows()
         self.save_ccdc_number()
         try:
             self.cif.save()
@@ -1129,23 +1147,78 @@ def save_current_cif_file(self) -> Union[bool, None]:
             show_general_warning('Can not save file: ' + str(e))
             return False
 
-    def store_data_from_table_rows(self, table: MyCifTable) -> None:
+    def store_data_from_table_rows(self) -> None:
         """
         Stores the data from the main table in the cif object.
         """
+        changes_cif: Optional[CifContainer] = None
+        if self.options.track_changes:
+            changes_cif = self.get_changes_cif(self.finalcif_changes_filename)
+        # makes sure also the currently edited item is saved:
+        self.ui.cif_main_table.setCurrentItem(None)
         for row in range(self.ui.cif_main_table.rows_count):
             vhead = self.ui.cif_main_table.vheader_text(row)
             if not self.is_row_a_cif_item(vhead):
                 continue
-            col_data = table.text(row, COL_DATA)
-            col_edit = table.text(row, COL_EDIT)
+            col_data = self.ui.cif_main_table.text(row, COL_DATA)
+            col_edit = self.ui.cif_main_table.text(row, COL_EDIT)
             if col_data and not col_edit and col_data != '?':
                 self.cif[vhead] = col_data
             if col_edit:
+                if self.cif[vhead] != col_edit and changes_cif:
+                    changes_cif[vhead] = col_edit
                 try:
                     self.cif[vhead] = col_edit
                 except (RuntimeError, ValueError, IOError) as e:
                     print('Can not take cif info from table:', e)
+            else:
+                if changes_cif:
+                    del changes_cif[vhead]
+        if changes_cif:
+            self.save_changed_loops(changes_cif)
+            try:
+                changes_cif.save(filename=self.finalcif_changes_filename)
+            except Exception as e:
+                print(f'Unable to save changes file: {e}')
+
+    def save_changed_loops(self, changes_cif: CifContainer):
+        """
+        previous_cif is the original unchanged cif that gets 'previous_cif'-finalcif.cif after saving.
+        previous_values contains its loops.
+        """
+        previous_cif = CifContainer(Path(strip_finalcif_of_name(self.cif.finalcif_file,
+                                                                till_name_ends=True)).with_suffix('.cif'))
+        previous_values = []
+        for loop2 in previous_cif.loops:
+            previous_values.append(loop2.values)
+        for loop in self.cif.loops:
+            if loop.values not in previous_values:
+                changes_cif.add_loop_to_cif(loop_tags=loop.tags, loop_values=loop.values)
+        changes_cif.save(filename=self.finalcif_changes_filename)
+
+    def get_changes_cif(self, finalcif_changes_file) -> CifContainer:
+        block_name = self.cif.current_block if self.cif.current_block else self.cif.block.name
+        block_name = block_name + '_changes'
+        changes_cif = CifContainer(file=finalcif_changes_file,
+                                   new_block=block_name if not finalcif_changes_file.exists() else '')
+        # new block of added cif is not loaded:
+        if block_name in changes_cif.doc:
+            changes_cif.load_this_block(list(changes_cif.doc).index(block_name))
+        return changes_cif
+
+    def load_changes_cif(self):
+        finalcif_changes_file = self.cif.finalcif_file_prefixed(prefix='', suffix='-finalcif_changes.cif',
+                                                                force_strip=True)
+        if not finalcif_changes_file.exists():
+            return
+        changes = CifContainer(finalcif_changes_file)
+        for item in changes.block:
+            if item.pair is not None:
+                key, value = item.pair
+                value = gemmi.cif.as_string(value).strip()
+                self.ui.cif_main_table.setText(key=key, column=COL_EDIT, color=None, txt=value)
+        for loop in changes.loops:
+            self.cif.add_loop_to_cif(loop_tags=loop.tags, loop_values=loop.values)
 
     def is_row_a_cif_item(self, vhead):
         is_cif = False
@@ -1326,6 +1399,8 @@ def _load_block(self, index: int):
                 raise
             unable_to_open_message(Path(self.cif.filename), not_ok)
         self.load_recent_cifs_list()
+        if self.options.track_changes:
+            self.load_changes_cif()
         self.make_loops_tables()
         if self.cif:
             self.set_shredcif_state()
@@ -1368,25 +1443,6 @@ def set_shredcif_state(self):
         else:
             self.ui.ShredCifButton.setDisabled(True)
 
-    def enable_buttons(self):
-        self.ui.appendCifPushButton.setEnabled(True)
-        self.ui.CheckcifButton.setEnabled(True)
-        self.ui.CheckcifHTMLOnlineButton.setEnabled(True)
-        self.ui.CheckcifPDFOnlineButton.setEnabled(True)
-        self.ui.SaveCifButton.setEnabled(True)
-        self.ui.ExploreDirButton.setEnabled(True)
-        self.ui.DetailsPushButton.setEnabled(True)
-        self.ui.SourcesPushButton.setEnabled(True)
-        self.ui.OptionsPushButton.setEnabled(True)
-        self.ui.ImportCifPushButton.setEnabled(True)
-        self.ui.CODpushButton.setEnabled(True)
-        self.ui.CCDCpushButton.setEnabled(True)
-        self.ui.LoopsPushButton.setEnabled(True)
-        if self.cif.is_multi_cif:
-            self.ui.CODpushButton.setDisabled(True)
-        else:
-            self.ui.CODpushButton.setEnabled(True)
-
     def append_cif(self):
         self.cif.save()
         self.load_cif_file(filepath=self.cif.finalcif_file)
@@ -1577,7 +1633,7 @@ def get_data_sources(self) -> None:
             ccdc = CCDCMail(self.cif)
             if ccdc.depnum > 0:
                 # The next line is necessary, otherwise reopening of a cif would not add the CCDC number:
-                if not '_database_code_depnum_ccdc_archive' in self.ui.cif_main_table.vheaderitems:
+                if '_database_code_depnum_ccdc_archive' not in self.ui.cif_main_table.vheaderitems:
                     # self.ui.cif_main_table.vheaderitems.insert(0, '_database_code_depnum_ccdc_archive')
                     self.add_row('_database_code_depnum_ccdc_archive', '', at_start=True)
                 txt = self.ui.cif_main_table.getTextFromKey('_database_code_depnum_ccdc_archive', COL_EDIT).strip()
@@ -1619,7 +1675,7 @@ def refresh_combo_boxes(self):
         combos_from_settings = self.settings.load_cif_keys_of_properties()
         for row_number in range(self.ui.cif_main_table.model().rowCount()):
             vhead_key = self.get_key_by_row_number(row_number)
-            if not vhead_key in self.ui.cif_main_table.vheaderitems:
+            if vhead_key not in self.ui.cif_main_table.vheaderitems:
                 self.ui.cif_main_table.vheaderitems.insert(row_number, vhead_key)
             # adding comboboxes:
             if vhead_key in combos_from_settings:
diff --git a/finalcif/cif/cif_file_io.py b/finalcif/cif/cif_file_io.py
index 08a0810a..4e5905f9 100644
--- a/finalcif/cif/cif_file_io.py
+++ b/finalcif/cif/cif_file_io.py
@@ -7,6 +7,7 @@
 #  ----------------------------------------------------------------------------
 import re
 from collections import namedtuple
+from functools import cache
 from pathlib import Path
 from typing import Dict, List, Tuple, Union, Generator, Type
 
@@ -27,6 +28,13 @@ class CifContainer():
     """
 
     def __init__(self, file: Union[Path, str], new_block: str = ''):
+        """
+
+        Args:
+            file: CIF file to open
+            new_block: Create a new block if a name is given. Otherwise, just
+                       the existing document is opened.
+        """
         if isinstance(file, str):
             self.fileobj = Path(file)
         elif isinstance(file, Path):
@@ -43,7 +51,7 @@ def __init__(self, file: Union[Path, str], new_block: str = ''):
         else:
             self.doc = self.read_file(str(self.fileobj.resolve(strict=True)))
         # Starting with first block, but can use others with subsequent self._onload():
-        self.block = self.doc[0]
+        self.block: gemmi.cif.Block = self.doc[0]
         self.shx = Shelxfile()
         self.shx.read_string(self.res_file_data[1:-1])
         self._on_load()
@@ -73,13 +81,15 @@ def finalcif_file(self) -> Path:
         filename = self.finalcif_file_prefixed(prefix='', suffix='-finalcif.cif')
         return filename
 
-    def finalcif_file_prefixed(self, prefix: str, suffix: str = '-finalcif.cif') -> Path:
+    def finalcif_file_prefixed(self, prefix: str, suffix: str = '-finalcif.cif', force_strip=True) -> Path:
         """
         The full path of the file with a prefix and '-finalcif.cif' attached to the end.
         The suffix needs '-finalcif' in order to contain the finalcif ending.
         "foo/bar/baz-finalcif.cif"
+
+        :param forece_strip: Forces to strip the filename also after the '-finalcif' string.
         """
-        file_witout_finalcif = strip_finalcif_of_name(Path(self.filename).stem)
+        file_witout_finalcif = strip_finalcif_of_name(Path(self.filename).stem, till_name_ends=force_strip)
         filename = self.path_base.joinpath(Path(prefix + file_witout_finalcif + suffix))
         return filename
 
@@ -105,7 +115,6 @@ def _on_load(self) -> None:
         # will not ok with non-ascii characters in the res file:
         self.chars_ok = True
         self.doc.check_for_duplicates()
-        self.hkl_extra_info = self._abs_hkl_details()
         self.order = order
         self.dsr_used = DSRFind(self.res_file_data).dsr_used
         self.atomic_struct: gemmi.SmallStructure = gemmi.make_small_structure_from_block(self.block)
@@ -115,6 +124,11 @@ def _on_load(self) -> None:
                 [x.upper() for x in self.block.find_loop('_atom_site_type_symbol')]))
         self.check_hkl_min_max()
 
+    @property
+    @cache
+    def hkl_extra_info(self):
+        return self._abs_hkl_details()
+
     def check_hkl_min_max(self) -> None:
         if not all([self['_diffrn_reflns_limit_h_min'], self['_diffrn_reflns_limit_h_max'],
                     self['_diffrn_reflns_limit_k_min'], self['_diffrn_reflns_limit_k_max'],
@@ -182,7 +196,11 @@ def __setitem__(self, key: str, value: str) -> None:
         self.set_pair_delimited(key, value)
 
     def __delitem__(self, key: str):
-        self.block.find_pair_item(key).erase()
+        try:
+            self.block.find_pair_item(key).erase()
+        except AttributeError:
+            pass
+            # key is not in block
 
     def __contains__(self, item):
         return bool(self.__getitem__(item))
@@ -216,7 +234,7 @@ def set_pair_delimited(self, key: str, txt: str):
             else:
                 self.block.set_pair(key, quote(txt))
 
-    def save(self, filename: Path = None) -> None:
+    def save(self, filename: Union[Path, None] = None) -> None:
         """
         Saves the current cif file.
         :param filename:  Name to save cif file to.
@@ -404,6 +422,11 @@ def loops(self) -> List[gemmi.cif.Loop]:
                 loops.append(b.loop)
         return loops
 
+    def add_loop_to_cif(self, loop_tags: List[str], loop_values: Union[list, tuple]):
+        gemmi_loop = self.init_loop(loop_tags)
+        for row in list(grouper(loop_values, len(loop_tags))):
+            gemmi_loop.add_row(row)
+
     @property
     def n_loops(self):
         return len(self.loops)
diff --git a/finalcif/datafiles/bruker_data.py b/finalcif/datafiles/bruker_data.py
index 5023e45e..f5796df0 100644
--- a/finalcif/datafiles/bruker_data.py
+++ b/finalcif/datafiles/bruker_data.py
@@ -83,7 +83,7 @@ def __init__(self, app, cif: CifContainer):
             frame_name = self.frame_header.filename.name
         except FileNotFoundError:
             frame_name = ''
-        if self.cif.solution_program_details:
+        if not self.cif['_computing_structure_solution'] and self.cif.solution_program_details:
             solution_program = (self.cif.solution_program_details, self.cif.fileobj.name)
         if self.cif['_computing_structure_solution']:
             solution_program = (gcif.as_string(self.cif['_computing_structure_solution']), self.cif.fileobj.name)
diff --git a/finalcif/gui/custom_classes.py b/finalcif/gui/custom_classes.py
index 1baf202a..167cf9b4 100644
--- a/finalcif/gui/custom_classes.py
+++ b/finalcif/gui/custom_classes.py
@@ -4,7 +4,7 @@
 from PyQt5.QtCore import QEvent, QObject, Qt
 from PyQt5.QtGui import QColor, QKeySequence, QBrush
 from PyQt5.QtWidgets import QAbstractScrollArea, QTableWidget, \
-    QTableWidgetItem, QWidget, QApplication, QShortcut
+    QTableWidgetItem, QWidget, QApplication, QShortcut, QHeaderView
 
 from finalcif.cif.text import retranslate_delimiter
 from finalcif.gui.combobox import MyComboBox
@@ -240,6 +240,14 @@ def vheader_text(self, row):
         vhead = self.model().headerData(row, Qt.Vertical)
         return str(vhead)
 
+    def distribute_cif_main_table_columns_evenly(self) -> None:
+        hheader = self.horizontalHeader()
+        hheader.setSectionResizeMode(COL_CIF, QHeaderView.Stretch)
+        hheader.setSectionResizeMode(COL_DATA, QHeaderView.Stretch)
+        hheader.setSectionResizeMode(COL_EDIT, QHeaderView.Stretch)
+        hheader.setAlternatingRowColors(True)
+        self.verticalHeader().setAlternatingRowColors(True)
+
 
 class MyTableWidgetItem(QTableWidgetItem):
 
diff --git a/finalcif/gui/finalcif_gui.py b/finalcif/gui/finalcif_gui.py
index 5ffccbb9..87f91cfa 100644
--- a/finalcif/gui/finalcif_gui.py
+++ b/finalcif/gui/finalcif_gui.py
@@ -924,23 +924,10 @@ def setupUi(self, FinalCifWindow):
         self.gridLayout_12.addWidget(self.BackFromOptionspPushButton, 8, 0, 1, 1)
         spacerItem16 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
         self.gridLayout_12.addItem(spacerItem16, 9, 0, 1, 1)
-        self.groupBox_COD = QtWidgets.QGroupBox(self.page_options)
-        self.groupBox_COD.setObjectName("groupBox_COD")
-        self.formLayout_6 = QtWidgets.QFormLayout(self.groupBox_COD)
-        self.formLayout_6.setObjectName("formLayout_6")
-        self.label_7 = QtWidgets.QLabel(self.groupBox_COD)
-        self.label_7.setObjectName("label_7")
-        self.formLayout_6.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.label_7)
-        self.CODURLTextedit = QtWidgets.QLineEdit(self.groupBox_COD)
-        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
-        sizePolicy.setHorizontalStretch(0)
-        sizePolicy.setVerticalStretch(0)
-        sizePolicy.setHeightForWidth(self.CODURLTextedit.sizePolicy().hasHeightForWidth())
-        self.CODURLTextedit.setSizePolicy(sizePolicy)
-        self.CODURLTextedit.setMinimumSize(QtCore.QSize(300, 0))
-        self.CODURLTextedit.setObjectName("CODURLTextedit")
-        self.formLayout_6.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.CODURLTextedit)
-        self.gridLayout_12.addWidget(self.groupBox_COD, 3, 0, 1, 1)
+        spacerItem17 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_12.addItem(spacerItem17, 8, 1, 1, 3)
+        spacerItem18 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.gridLayout_12.addItem(spacerItem18, 7, 0, 1, 1)
         self.groupBox_8 = QtWidgets.QGroupBox(self.page_options)
         self.groupBox_8.setObjectName("groupBox_8")
         self.verticalLayout_34 = QtWidgets.QVBoxLayout(self.groupBox_8)
@@ -951,15 +938,15 @@ def setupUi(self, FinalCifWindow):
         self.label_18 = QtWidgets.QLabel(self.groupBox_8)
         self.label_18.setObjectName("label_18")
         self.verticalLayout_34.addWidget(self.label_18)
-        spacerItem17 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
-        self.verticalLayout_34.addItem(spacerItem17)
+        spacerItem19 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
+        self.verticalLayout_34.addItem(spacerItem19)
         self.ImportAllTemplatesPushButton = QtWidgets.QPushButton(self.groupBox_8)
         self.ImportAllTemplatesPushButton.setObjectName("ImportAllTemplatesPushButton")
         self.verticalLayout_34.addWidget(self.ImportAllTemplatesPushButton, 0, QtCore.Qt.AlignLeft)
         self.label_17 = QtWidgets.QLabel(self.groupBox_8)
         self.label_17.setObjectName("label_17")
         self.verticalLayout_34.addWidget(self.label_17)
-        self.gridLayout_12.addWidget(self.groupBox_8, 6, 0, 1, 1)
+        self.gridLayout_12.addWidget(self.groupBox_8, 6, 0, 1, 2)
         self.groupBox_7 = QtWidgets.QGroupBox(self.page_options)
         self.groupBox_7.setObjectName("groupBox_7")
         self.formLayout_4 = QtWidgets.QFormLayout(self.groupBox_7)
@@ -976,11 +963,7 @@ def setupUi(self, FinalCifWindow):
         self.CheckCIFServerURLTextedit.setMinimumSize(QtCore.QSize(300, 0))
         self.CheckCIFServerURLTextedit.setObjectName("CheckCIFServerURLTextedit")
         self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.CheckCIFServerURLTextedit)
-        self.gridLayout_12.addWidget(self.groupBox_7, 2, 0, 1, 1)
-        spacerItem18 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_12.addItem(spacerItem18, 8, 1, 1, 3)
-        spacerItem19 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
-        self.gridLayout_12.addItem(spacerItem19, 7, 0, 1, 1)
+        self.gridLayout_12.addWidget(self.groupBox_7, 2, 0, 1, 2)
         self.groupBox_5 = QtWidgets.QGroupBox(self.page_options)
         self.groupBox_5.setObjectName("groupBox_5")
         self.formLayout_5 = QtWidgets.QFormLayout(self.groupBox_5)
@@ -1076,7 +1059,34 @@ def setupUi(self, FinalCifWindow):
         spacerItem23 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
         self.verticalLayout_36.addItem(spacerItem23)
         self.formLayout_5.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.verticalLayout_36)
-        self.gridLayout_12.addWidget(self.groupBox_5, 1, 0, 1, 1)
+        self.gridLayout_12.addWidget(self.groupBox_5, 1, 0, 1, 4)
+        self.groupBox_COD = QtWidgets.QGroupBox(self.page_options)
+        self.groupBox_COD.setObjectName("groupBox_COD")
+        self.formLayout_6 = QtWidgets.QFormLayout(self.groupBox_COD)
+        self.formLayout_6.setObjectName("formLayout_6")
+        self.label_7 = QtWidgets.QLabel(self.groupBox_COD)
+        self.label_7.setObjectName("label_7")
+        self.formLayout_6.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.label_7)
+        self.CODURLTextedit = QtWidgets.QLineEdit(self.groupBox_COD)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.CODURLTextedit.sizePolicy().hasHeightForWidth())
+        self.CODURLTextedit.setSizePolicy(sizePolicy)
+        self.CODURLTextedit.setMinimumSize(QtCore.QSize(300, 0))
+        self.CODURLTextedit.setObjectName("CODURLTextedit")
+        self.formLayout_6.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.CODURLTextedit)
+        self.gridLayout_12.addWidget(self.groupBox_COD, 2, 2, 1, 2)
+        self.groupBox_10 = QtWidgets.QGroupBox(self.page_options)
+        self.groupBox_10.setObjectName("groupBox_10")
+        self.verticalLayout_37 = QtWidgets.QVBoxLayout(self.groupBox_10)
+        self.verticalLayout_37.setObjectName("verticalLayout_37")
+        self.trackChangesCifCheckBox = QtWidgets.QCheckBox(self.groupBox_10)
+        self.trackChangesCifCheckBox.setObjectName("trackChangesCifCheckBox")
+        self.verticalLayout_37.addWidget(self.trackChangesCifCheckBox)
+        spacerItem24 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.verticalLayout_37.addItem(spacerItem24)
+        self.gridLayout_12.addWidget(self.groupBox_10, 6, 2, 1, 2)
         self.MainStackedWidget.addWidget(self.page_options)
         self.page_Loops = QtWidgets.QWidget()
         self.page_Loops.setObjectName("page_Loops")
@@ -1089,10 +1099,10 @@ def setupUi(self, FinalCifWindow):
         self.tab_2.setObjectName("tab_2")
         self.gridLayout_2 = QtWidgets.QGridLayout(self.tab_2)
         self.gridLayout_2.setObjectName("gridLayout_2")
-        spacerItem24 = QtWidgets.QSpacerItem(535, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_2.addItem(spacerItem24, 0, 2, 1, 1)
-        spacerItem25 = QtWidgets.QSpacerItem(20, 162, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
-        self.gridLayout_2.addItem(spacerItem25, 1, 0, 1, 1)
+        spacerItem25 = QtWidgets.QSpacerItem(535, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_2.addItem(spacerItem25, 0, 2, 1, 1)
+        spacerItem26 = QtWidgets.QSpacerItem(20, 162, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.gridLayout_2.addItem(spacerItem26, 1, 0, 1, 1)
         self.groupBox_9 = QtWidgets.QGroupBox(self.tab_2)
         self.groupBox_9.setObjectName("groupBox_9")
         self.verticalLayout_23 = QtWidgets.QVBoxLayout(self.groupBox_9)
@@ -1164,16 +1174,16 @@ def setupUi(self, FinalCifWindow):
         self.verticalLayout_32.addWidget(self.SaveAuthorLoopToTemplateButton, 0, QtCore.Qt.AlignRight)
         self.verticalLayout_23.addLayout(self.verticalLayout_32)
         self.gridLayout_2.addWidget(self.groupBox_9, 0, 0, 1, 1)
-        spacerItem26 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_2.addItem(spacerItem26, 0, 1, 1, 1)
+        spacerItem27 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_2.addItem(spacerItem27, 0, 1, 1, 1)
         self.LoopsTabWidget.addTab(self.tab_2, "")
         self.verticalLayout_9.addWidget(self.LoopsTabWidget)
         self.gridLayout_16 = QtWidgets.QGridLayout()
         self.gridLayout_16.setObjectName("gridLayout_16")
-        spacerItem27 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_16.addItem(spacerItem27, 0, 3, 1, 1)
-        spacerItem28 = QtWidgets.QSpacerItem(20, 28, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
-        self.gridLayout_16.addItem(spacerItem28, 4, 0, 1, 1)
+        spacerItem28 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_16.addItem(spacerItem28, 0, 3, 1, 1)
+        spacerItem29 = QtWidgets.QSpacerItem(20, 28, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
+        self.gridLayout_16.addItem(spacerItem29, 4, 0, 1, 1)
         self.revertLoopsPushButton = QtWidgets.QPushButton(self.page_Loops)
         self.revertLoopsPushButton.setObjectName("revertLoopsPushButton")
         self.gridLayout_16.addWidget(self.revertLoopsPushButton, 0, 2, 1, 1)
@@ -1186,8 +1196,8 @@ def setupUi(self, FinalCifWindow):
         self.BackFromLoopsPushButton.setMinimumSize(QtCore.QSize(120, 0))
         self.BackFromLoopsPushButton.setObjectName("BackFromLoopsPushButton")
         self.gridLayout_16.addWidget(self.BackFromLoopsPushButton, 0, 0, 1, 1)
-        spacerItem29 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_16.addItem(spacerItem29, 0, 1, 1, 1)
+        spacerItem30 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_16.addItem(spacerItem30, 0, 1, 1, 1)
         self.BackToCODPushButton = QtWidgets.QPushButton(self.page_Loops)
         self.BackToCODPushButton.setObjectName("BackToCODPushButton")
         self.gridLayout_16.addWidget(self.BackToCODPushButton, 1, 0, 1, 1)
@@ -1264,8 +1274,8 @@ def setupUi(self, FinalCifWindow):
         self.SavePushButton = QtWidgets.QPushButton(self.frame)
         self.SavePushButton.setObjectName("SavePushButton")
         self.horizontalLayout_2.addWidget(self.SavePushButton)
-        spacerItem30 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.horizontalLayout_2.addItem(spacerItem30)
+        spacerItem31 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout_2.addItem(spacerItem31)
         self.verticalLayout_15.addWidget(self.frame)
         self.ResponsesTabWidget.addTab(self.ResponsesTabWidgetPage2, "")
         self.verticalLayout_12.addWidget(self.ResponsesTabWidget)
@@ -1283,8 +1293,8 @@ def setupUi(self, FinalCifWindow):
         self.label_5.setMinimumSize(QtCore.QSize(0, 20))
         self.label_5.setObjectName("label_5")
         self.verticalLayout_13.addWidget(self.label_5)
-        spacerItem31 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
-        self.verticalLayout_13.addItem(spacerItem31)
+        spacerItem32 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.verticalLayout_13.addItem(spacerItem32)
         self.CheckCIFResultsTabWidget.addTab(self.pdf_page, "")
         self.gridLayout_8.addWidget(self.CheckCIFResultsTabWidget, 1, 0, 1, 8)
         self.groupBox_71 = QtWidgets.QGroupBox(self.page_checkcif)
@@ -1338,16 +1348,16 @@ def setupUi(self, FinalCifWindow):
         self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
         self.horizontalLayout_3.setObjectName("horizontalLayout_3")
         self.gridLayout_8.addWidget(self.ButtonFrame, 2, 0, 1, 7)
-        spacerItem32 = QtWidgets.QSpacerItem(225, 47, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_8.addItem(spacerItem32, 4, 6, 3, 1)
+        spacerItem33 = QtWidgets.QSpacerItem(225, 47, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_8.addItem(spacerItem33, 4, 6, 3, 1)
         self.BackFromPlatonPushButton = QtWidgets.QPushButton(self.page_checkcif)
         self.BackFromPlatonPushButton.setMinimumSize(QtCore.QSize(160, 0))
         self.BackFromPlatonPushButton.setObjectName("BackFromPlatonPushButton")
         self.gridLayout_8.addWidget(self.BackFromPlatonPushButton, 5, 3, 1, 1)
-        spacerItem33 = QtWidgets.QSpacerItem(13, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_8.addItem(spacerItem33, 5, 1, 1, 2)
-        spacerItem34 = QtWidgets.QSpacerItem(13, 47, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_8.addItem(spacerItem34, 4, 4, 3, 1)
+        spacerItem34 = QtWidgets.QSpacerItem(13, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_8.addItem(spacerItem34, 5, 1, 1, 2)
+        spacerItem35 = QtWidgets.QSpacerItem(13, 47, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_8.addItem(spacerItem35, 4, 4, 3, 1)
         self.MainStackedWidget.addWidget(self.page_checkcif)
         self.page_cod = QtWidgets.QWidget()
         self.page_cod.setObjectName("page_cod")
@@ -1374,8 +1384,8 @@ def setupUi(self, FinalCifWindow):
         self.publishedDepositionRadioButton = QtWidgets.QRadioButton(self.frame_for_radiobuttons)
         self.publishedDepositionRadioButton.setObjectName("publishedDepositionRadioButton")
         self.horizontalLayout_radiobuttons.addWidget(self.publishedDepositionRadioButton)
-        spacerItem35 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
-        self.horizontalLayout_radiobuttons.addItem(spacerItem35)
+        spacerItem36 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout_radiobuttons.addItem(spacerItem36)
         self.verticalLayout_28.addLayout(self.horizontalLayout_radiobuttons)
         self.gridLayout_22.addWidget(self.frame_for_radiobuttons, 0, 1, 1, 1)
         self.gridLayout_19 = QtWidgets.QGridLayout()
@@ -1400,8 +1410,8 @@ def setupUi(self, FinalCifWindow):
         self.Upload_hkl_pushButton = QtWidgets.QPushButton(self.page_cod)
         self.Upload_hkl_pushButton.setObjectName("Upload_hkl_pushButton")
         self.horizontalLayout_11.addWidget(self.Upload_hkl_pushButton)
-        spacerItem36 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.horizontalLayout_11.addItem(spacerItem36)
+        spacerItem37 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout_11.addItem(spacerItem37)
         self.gridLayout_19.addLayout(self.horizontalLayout_11, 3, 1, 1, 1)
         self.userEmailLineEdit = QtWidgets.QLineEdit(self.page_cod)
         self.userEmailLineEdit.setInputMethodHints(QtCore.Qt.ImhEmailCharactersOnly|QtCore.Qt.ImhLowercaseOnly|QtCore.Qt.ImhNoAutoUppercase)
@@ -1437,8 +1447,8 @@ def setupUi(self, FinalCifWindow):
         self.verticalLayout_30.addWidget(self.label_10)
         self.gridLayout_20 = QtWidgets.QGridLayout()
         self.gridLayout_20.setObjectName("gridLayout_20")
-        spacerItem37 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_20.addItem(spacerItem37, 0, 2, 1, 1)
+        spacerItem38 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_20.addItem(spacerItem38, 0, 2, 1, 1)
         self.ContactAuthorLabel = QtWidgets.QLabel(self.page_personal)
         self.ContactAuthorLabel.setObjectName("ContactAuthorLabel")
         self.gridLayout_20.addWidget(self.ContactAuthorLabel, 1, 0, 1, 1)
@@ -1465,8 +1475,8 @@ def setupUi(self, FinalCifWindow):
         self.label_12.setObjectName("label_12")
         self.gridLayout_20.addWidget(self.label_12, 2, 0, 1, 1)
         self.verticalLayout_30.addLayout(self.gridLayout_20)
-        spacerItem38 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
-        self.verticalLayout_30.addItem(spacerItem38)
+        spacerItem39 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.verticalLayout_30.addItem(spacerItem39)
         self.depositionOptionsStackedWidget.addWidget(self.page_personal)
         self.page_prepublication = QtWidgets.QWidget()
         self.page_prepublication.setObjectName("page_prepublication")
@@ -1474,8 +1484,8 @@ def setupUi(self, FinalCifWindow):
         self.verticalLayout_25.setObjectName("verticalLayout_25")
         self.gridLayout_21 = QtWidgets.QGridLayout()
         self.gridLayout_21.setObjectName("gridLayout_21")
-        spacerItem39 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_21.addItem(spacerItem39, 0, 2, 1, 1)
+        spacerItem40 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_21.addItem(spacerItem40, 0, 2, 1, 1)
         self.embargoTimeInMonthsSpinBox = QtWidgets.QSpinBox(self.page_prepublication)
         self.embargoTimeInMonthsSpinBox.setMinimum(6)
         self.embargoTimeInMonthsSpinBox.setMaximum(12)
@@ -1496,8 +1506,8 @@ def setupUi(self, FinalCifWindow):
         self.verticalLayout_25.addLayout(self.gridLayout_21)
         self.gridLayout_author_prepubl = QtWidgets.QGridLayout()
         self.gridLayout_author_prepubl.setObjectName("gridLayout_author_prepubl")
-        spacerItem40 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_author_prepubl.addItem(spacerItem40, 0, 3, 1, 1)
+        spacerItem41 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_author_prepubl.addItem(spacerItem41, 0, 3, 1, 1)
         self.authorsFullNamePersonalLabel_2 = QtWidgets.QLabel(self.page_prepublication)
         self.authorsFullNamePersonalLabel_2.setObjectName("authorsFullNamePersonalLabel_2")
         self.gridLayout_author_prepubl.addWidget(self.authorsFullNamePersonalLabel_2, 0, 1, 1, 1)
@@ -1524,8 +1534,8 @@ def setupUi(self, FinalCifWindow):
         self.ContactEmailLineEdit_2.setObjectName("ContactEmailLineEdit_2")
         self.gridLayout_author_prepubl.addWidget(self.ContactEmailLineEdit_2, 2, 2, 1, 1)
         self.verticalLayout_25.addLayout(self.gridLayout_author_prepubl)
-        spacerItem41 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
-        self.verticalLayout_25.addItem(spacerItem41)
+        spacerItem42 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.verticalLayout_25.addItem(spacerItem42)
         self.depositionOptionsStackedWidget.addWidget(self.page_prepublication)
         self.page_published = QtWidgets.QWidget()
         self.page_published.setObjectName("page_published")
@@ -1540,8 +1550,8 @@ def setupUi(self, FinalCifWindow):
         self.cod_database_code_Label = QtWidgets.QLabel(self.page_published)
         self.cod_database_code_Label.setObjectName("cod_database_code_Label")
         self.gridLayout_23.addWidget(self.cod_database_code_Label, 1, 0, 1, 1)
-        spacerItem42 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_23.addItem(spacerItem42, 1, 3, 1, 1)
+        spacerItem43 = QtWidgets.QSpacerItem(80, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_23.addItem(spacerItem43, 1, 3, 1, 1)
         self.label_11 = QtWidgets.QLabel(self.page_published)
         self.label_11.setObjectName("label_11")
         self.gridLayout_23.addWidget(self.label_11, 0, 0, 1, 2)
@@ -1562,8 +1572,8 @@ def setupUi(self, FinalCifWindow):
         self.label_14.setObjectName("label_14")
         self.verticalLayout_26.addWidget(self.label_14)
         self.verticalLayout_27.addLayout(self.verticalLayout_26)
-        spacerItem43 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
-        self.verticalLayout_27.addItem(spacerItem43)
+        spacerItem44 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.verticalLayout_27.addItem(spacerItem44)
         self.depositionOptionsStackedWidget.addWidget(self.page_published)
         self.page_deposition_output = QtWidgets.QWidget()
         self.page_deposition_output.setObjectName("page_deposition_output")
@@ -1601,10 +1611,10 @@ def setupUi(self, FinalCifWindow):
         self.refreshDepositListPushButton.setAutoDefault(False)
         self.refreshDepositListPushButton.setObjectName("refreshDepositListPushButton")
         self.gridLayout_18.addWidget(self.refreshDepositListPushButton, 1, 1, 1, 1)
-        spacerItem44 = QtWidgets.QSpacerItem(1, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_18.addItem(spacerItem44, 1, 0, 1, 1)
         spacerItem45 = QtWidgets.QSpacerItem(1, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_18.addItem(spacerItem45, 1, 2, 1, 1)
+        self.gridLayout_18.addItem(spacerItem45, 1, 0, 1, 1)
+        spacerItem46 = QtWidgets.QSpacerItem(1, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_18.addItem(spacerItem46, 1, 2, 1, 1)
         self.CODtableWidget = QtWidgets.QTableWidget(self.StructuresListGroupBox)
         self.CODtableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
         self.CODtableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
@@ -1631,13 +1641,13 @@ def setupUi(self, FinalCifWindow):
         self.BackFromDepositPushButton.setMinimumSize(QtCore.QSize(160, 0))
         self.BackFromDepositPushButton.setObjectName("BackFromDepositPushButton")
         self.horizontalLayout_10.addWidget(self.BackFromDepositPushButton)
-        spacerItem46 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.horizontalLayout_10.addItem(spacerItem46)
+        spacerItem47 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout_10.addItem(spacerItem47)
         self.depositCIFpushButton = QtWidgets.QPushButton(self.page_cod)
         self.depositCIFpushButton.setObjectName("depositCIFpushButton")
         self.horizontalLayout_10.addWidget(self.depositCIFpushButton)
-        spacerItem47 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
-        self.horizontalLayout_10.addItem(spacerItem47)
+        spacerItem48 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout_10.addItem(spacerItem48)
         self.gridLayout_17.addLayout(self.horizontalLayout_10, 1, 0, 1, 2)
         self.MainStackedWidget.addWidget(self.page_cod)
         self.page_textTemplate = QtWidgets.QWidget()
@@ -1665,8 +1675,8 @@ def setupUi(self, FinalCifWindow):
         self.datanameComboBox.setFrame(True)
         self.datanameComboBox.setObjectName("datanameComboBox")
         self.gridLayout_6.addWidget(self.datanameComboBox, 0, 1, 1, 1)
-        spacerItem48 = QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
-        self.gridLayout_6.addItem(spacerItem48, 0, 6, 1, 1)
+        spacerItem49 = QtWidgets.QSpacerItem(10, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout_6.addItem(spacerItem49, 0, 6, 1, 1)
         self.appendCifPushButton = QtWidgets.QPushButton(self.CifDataItemsFrame)
         self.appendCifPushButton.setObjectName("appendCifPushButton")
         self.gridLayout_6.addWidget(self.appendCifPushButton, 0, 2, 1, 1)
@@ -1686,7 +1696,7 @@ def setupUi(self, FinalCifWindow):
         self.TemplatesStackedWidget.setCurrentIndex(0)
         self.EquipmentTemplatesStackedWidget.setCurrentIndex(0)
         self.PropertiesTemplatesStackedWidget.setCurrentIndex(1)
-        self.MainStackedWidget.setCurrentIndex(1)
+        self.MainStackedWidget.setCurrentIndex(4)
         self.LoopsTabWidget.setCurrentIndex(0)
         self.CheckCIFResultsTabWidget.setCurrentIndex(1)
         self.ResponsesTabWidget.setCurrentIndex(0)
@@ -1894,9 +1904,6 @@ def retranslateUi(self, FinalCifWindow):
         item.setText(_translate("FinalCifWindow", "Data Source"))
         self.BackSourcesPushButton.setText(_translate("FinalCifWindow", "Back to CIF Table"))
         self.BackFromOptionspPushButton.setText(_translate("FinalCifWindow", "Back to Main Table"))
-        self.groupBox_COD.setTitle(_translate("FinalCifWindow", "Crystallography Open Database"))
-        self.label_7.setText(_translate("FinalCifWindow", "COD deposit URL:"))
-        self.CODURLTextedit.setText(_translate("FinalCifWindow", "https://www.crystallography.net/cod/cgi-bin/cif-deposit.pl"))
         self.groupBox_8.setTitle(_translate("FinalCifWindow", "Export"))
         self.ExportAllTemplatesPushButton.setText(_translate("FinalCifWindow", "Export all Templates"))
         self.label_18.setText(_translate("FinalCifWindow", "Exports all templates from Equipment, Properties and Text snippets to a single file."))
@@ -1919,6 +1926,11 @@ def retranslateUi(self, FinalCifWindow):
         self.ReportTextCheckBox.setText(_translate("FinalCifWindow", "No report text in structure report"))
         self.HAtomsCheckBox.setText(_translate("FinalCifWindow", "No bonds and angles to hydrogen atoms"))
         self.ADPTableCheckBox.setText(_translate("FinalCifWindow", "Add ADP table"))
+        self.groupBox_COD.setTitle(_translate("FinalCifWindow", "Crystallography Open Database"))
+        self.label_7.setText(_translate("FinalCifWindow", "COD deposit URL:"))
+        self.CODURLTextedit.setText(_translate("FinalCifWindow", "https://www.crystallography.net/cod/cgi-bin/cif-deposit.pl"))
+        self.groupBox_10.setTitle(_translate("FinalCifWindow", "General Options"))
+        self.trackChangesCifCheckBox.setText(_translate("FinalCifWindow", "Track CIF changes in separate file \"[name]-finalcif_changes.cif\"."))
         self.groupBox_9.setTitle(_translate("FinalCifWindow", "Publication Authors"))
         self.label_20.setText(_translate("FinalCifWindow", "Details about the authors of a manuscript submitted for publication.\n"
 "Contact authors should always also appear as regular authors."))
diff --git a/finalcif/gui/finalcif_gui.ui b/finalcif/gui/finalcif_gui.ui
index a9fdc470..a6e76518 100644
--- a/finalcif/gui/finalcif_gui.ui
+++ b/finalcif/gui/finalcif_gui.ui
@@ -1046,7 +1046,7 @@
         <item row="1" column="0" colspan="13">
          <widget class="MyMainStackedWidget" name="MainStackedWidget">
           <property name="currentIndex">
-           <number>1</number>
+           <number>4</number>
           </property>
           <widget class="QWidget" name="page_MainTable">
            <layout class="QVBoxLayout" name="verticalLayout">
@@ -2202,42 +2202,36 @@ The data source will be ignored until next program restart.</string>
               </property>
              </spacer>
             </item>
-            <item row="3" column="0">
-             <widget class="QGroupBox" name="groupBox_COD">
-              <property name="title">
-               <string>Crystallography Open Database</string>
+            <item row="8" column="1" colspan="3">
+             <spacer name="horizontalSpacer_14">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
               </property>
-              <layout class="QFormLayout" name="formLayout_6">
-               <item row="0" column="0" colspan="2">
-                <widget class="QLabel" name="label_7">
-                 <property name="text">
-                  <string>COD deposit URL:</string>
-                 </property>
-                </widget>
-               </item>
-               <item row="1" column="0" colspan="2">
-                <widget class="QLineEdit" name="CODURLTextedit">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-                   <horstretch>0</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="minimumSize">
-                  <size>
-                   <width>300</width>
-                   <height>0</height>
-                  </size>
-                 </property>
-                 <property name="text">
-                  <string>https://www.crystallography.net/cod/cgi-bin/cif-deposit.pl</string>
-                 </property>
-                </widget>
-               </item>
-              </layout>
-             </widget>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item row="7" column="0">
+             <spacer name="verticalSpacer_6">
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="sizeType">
+               <enum>QSizePolicy::Expanding</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>20</width>
+                <height>40</height>
+               </size>
+              </property>
+             </spacer>
             </item>
-            <item row="6" column="0">
+            <item row="6" column="0" colspan="2">
              <widget class="QGroupBox" name="groupBox_8">
               <property name="title">
                <string>Export</string>
@@ -2290,7 +2284,7 @@ The data source will be ignored until next program restart.</string>
               </layout>
              </widget>
             </item>
-            <item row="2" column="0">
+            <item row="2" column="0" colspan="2">
              <widget class="QGroupBox" name="groupBox_7">
               <property name="title">
                <string>CheckCIF Server</string>
@@ -2325,36 +2319,7 @@ The data source will be ignored until next program restart.</string>
               </layout>
              </widget>
             </item>
-            <item row="8" column="1" colspan="3">
-             <spacer name="horizontalSpacer_14">
-              <property name="orientation">
-               <enum>Qt::Horizontal</enum>
-              </property>
-              <property name="sizeHint" stdset="0">
-               <size>
-                <width>40</width>
-                <height>20</height>
-               </size>
-              </property>
-             </spacer>
-            </item>
-            <item row="7" column="0">
-             <spacer name="verticalSpacer_6">
-              <property name="orientation">
-               <enum>Qt::Vertical</enum>
-              </property>
-              <property name="sizeType">
-               <enum>QSizePolicy::Expanding</enum>
-              </property>
-              <property name="sizeHint" stdset="0">
-               <size>
-                <width>20</width>
-                <height>40</height>
-               </size>
-              </property>
-             </spacer>
-            </item>
-            <item row="1" column="0">
+            <item row="1" column="0" colspan="4">
              <widget class="QGroupBox" name="groupBox_5">
               <property name="title">
                <string>Report Options</string>
@@ -2594,6 +2559,70 @@ The data source will be ignored until next program restart.</string>
               </layout>
              </widget>
             </item>
+            <item row="2" column="2" colspan="2">
+             <widget class="QGroupBox" name="groupBox_COD">
+              <property name="title">
+               <string>Crystallography Open Database</string>
+              </property>
+              <layout class="QFormLayout" name="formLayout_6">
+               <item row="0" column="0" colspan="2">
+                <widget class="QLabel" name="label_7">
+                 <property name="text">
+                  <string>COD deposit URL:</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="0" colspan="2">
+                <widget class="QLineEdit" name="CODURLTextedit">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>300</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string>https://www.crystallography.net/cod/cgi-bin/cif-deposit.pl</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </widget>
+            </item>
+            <item row="6" column="2" colspan="2">
+             <widget class="QGroupBox" name="groupBox_10">
+              <property name="title">
+               <string>General Options</string>
+              </property>
+              <layout class="QVBoxLayout" name="verticalLayout_37">
+               <item>
+                <widget class="QCheckBox" name="trackChangesCifCheckBox">
+                 <property name="text">
+                  <string>Track CIF changes in separate file &quot;[name]-finalcif_changes.cif&quot;.</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="verticalSpacer_14">
+                 <property name="orientation">
+                  <enum>Qt::Vertical</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>40</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+              </layout>
+             </widget>
+            </item>
            </layout>
           </widget>
           <widget class="QWidget" name="page_Loops">
diff --git a/finalcif/gui/plaintextedit.py b/finalcif/gui/plaintextedit.py
index dc83202e..82ce6f16 100644
--- a/finalcif/gui/plaintextedit.py
+++ b/finalcif/gui/plaintextedit.py
@@ -1,4 +1,5 @@
 from contextlib import suppress
+from functools import cache
 
 from PyQt5.QtCore import pyqtSignal, Qt, QObject, QEvent, QSize
 from PyQt5.QtGui import QTextOption, QFontMetrics, QContextMenuEvent, QFont
@@ -24,8 +25,7 @@ def __init__(self, parent=None, *args, **kwargs):
         self.setParent(parent)
         self.cif_key = ''
         font = QFont()
-        # font.setFamily("Arial")
-        font.setPointSize(self.document().defaultFont().pointSize()+1)
+        font.setPointSize(self.document().defaultFont().pointSize() + 1)
         self.setFont(font)
         self.parent: 'MyCifTable' = parent
         self.setFocusPolicy(Qt.StrongFocus)
@@ -34,13 +34,17 @@ def __init__(self, parent=None, *args, **kwargs):
         self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
         self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
         self.setWordWrapMode(QTextOption.WordWrap)
-        self.fontmetric = QFontMetrics(self.document().defaultFont())
         self.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
         self.textChanged.connect(lambda: self.parent.resizeRowToContents(self.row))
 
     def __str__(self):
         return self.toPlainText()
 
+    @property
+    @cache
+    def fontmetric(self):
+        return QFontMetrics(self.document().defaultFont())
+
     def contextMenuEvent(self, event: QContextMenuEvent):
         menu = self.createStandardContextMenu(event.pos())
         action_copy_vhead = menu.addAction("Copy CIF Keyword")
diff --git a/finalcif/tools/download.py b/finalcif/tools/download.py
index d50e3a91..ca35ae8a 100644
--- a/finalcif/tools/download.py
+++ b/finalcif/tools/download.py
@@ -38,7 +38,7 @@ def failed_to_load(self, txt: str) -> None:
     def download(self) -> None:
         # print('Downloading:', self.url)
         OS = sys.platform
-        user_agent = 'FinalCif v{} ({})'.format(VERSION, OS)
+        user_agent = f'FinalCif v{VERSION} ({OS})'
         headers = {
             'User-Agent': user_agent,
         }
diff --git a/finalcif/tools/misc.py b/finalcif/tools/misc.py
index 96c0f8f3..8f216799 100644
--- a/finalcif/tools/misc.py
+++ b/finalcif/tools/misc.py
@@ -184,11 +184,12 @@ def g(*a, **kw):
         return g
 
 
-def strip_finalcif_of_name(pth: str) -> str:
+def strip_finalcif_of_name(pth: Union[str, Path], till_name_ends=False) -> str:
     """
     Strips '-finalcif' from the stem path
     """
-    return re.sub('-finalcif$', '', pth)
+    pth = str(pth)
+    return re.sub(f'-finalcif{".*" if till_name_ends else ""}$', '', pth)
 
 
 def flatten(lis: list) -> list:
diff --git a/finalcif/tools/options.py b/finalcif/tools/options.py
index e3de11b2..75011998 100644
--- a/finalcif/tools/options.py
+++ b/finalcif/tools/options.py
@@ -21,6 +21,7 @@ def _connect_signal_and_slots(self):
         self.ui.CheckCIFServerURLTextedit.textChanged.connect(self._state_changed)
         self.ui.CODURLTextedit.textChanged.connect(self._state_changed)
         self.ui.ADPTableCheckBox.stateChanged.connect(self._state_changed)
+        self.ui.trackChangesCifCheckBox.stateChanged.connect(self._state_changed)
 
     def show_options(self):
         """
@@ -33,6 +34,7 @@ def show_options(self):
         self.ui.CheckCIFServerURLTextedit.setText(self.checkcif_url)
         self.ui.CODURLTextedit.setText(self.cod_url)
         self.ui.ADPTableCheckBox.setChecked(self.report_adp)
+        self.ui.trackChangesCifCheckBox.setChecked(self.track_changes)
         #
         self.ui.MainStackedWidget.go_to_options_page()
 
@@ -49,6 +51,7 @@ def _state_changed(self):
             'hydrogen_bonds'         : True,
             'current_report_template': lw.row(lw.currentItem()),
             'cod_url'                : self.ui.CODURLTextedit.text(),
+            'track_changes'          : self.ui.trackChangesCifCheckBox.isChecked(),
         }
         # print('saving:', self._options)
         self.settings.save_options(self._options)
@@ -81,6 +84,13 @@ def without_h(self) -> bool:
         except KeyError:
             return False
 
+    @property
+    def track_changes(self) -> bool:
+        try:
+            return self.settings.load_options()['track_changes']
+        except KeyError:
+            return False
+
     @property
     def current_template(self) -> int:
         try:
diff --git a/finalcif/tools/settings.py b/finalcif/tools/settings.py
index 962d1441..197d52bb 100644
--- a/finalcif/tools/settings.py
+++ b/finalcif/tools/settings.py
@@ -145,10 +145,12 @@ def empty_deleted_list(self):
     def load_options(self) -> dict:
         options = self.load_settings_dict('Options', "options")
         if not options:
+            # These are the default values
             options = {'report_text'  : True,
                        'picture_width': 7.5,
                        'without_h'    : False,
                        'report_adp'   : True,
+                       'track_changes': False,
                        'checkcif_url' : 'https://checkcif.iucr.org/cgi-bin/checkcif_hkl.pl',
                        }
         # self.settings.endGroup()


Test patch:
diff --git a/tests/test_loops.py b/tests/test_loops.py
index 95b723fa..0c57e349 100644
--- a/tests/test_loops.py
+++ b/tests/test_loops.py
@@ -4,7 +4,6 @@
 #   this notice you can do whatever you want with this stuff. If we meet some day,
 #   and you think this stuff is worth it, you can buy me a beer in return.
 #   ----------------------------------------------------------------------------
-import os
 import unittest
 from pathlib import Path
 
@@ -21,14 +20,17 @@ class TestLoops(unittest.TestCase):
 
     def setUp(self) -> None:
         self.testcif = Path('tests/examples/1979688.cif').resolve()
+        Path('tests/examples/1979688-finalcif_changes.cif').unlink(missing_ok=True)
         self.myapp = AppWindow(self.testcif, unit_test=True)
         self.myapp.running_inside_unit_test = True
         self.myapp.hide()  # For full screen view
         self.myapp.ui.LoopsPushButton.click()
+        self.myapp.ui.trackChangesCifCheckBox.setChecked(False)
 
     def tearDown(self) -> None:
         self.myapp.cif.finalcif_file.unlink(missing_ok=True)
         self.myapp.close()
+        Path('tests/examples/1979688-finalcif_changes.cif').unlink(missing_ok=True)
 
     def get_index_of(self, loopkey: str = ''):
         tabw: QTabWidget = self.myapp.ui.LoopsTabWidget
@@ -79,10 +81,21 @@ def test_loop_edit_one_single_field(self):
         c = CifContainer(self.myapp.cif.finalcif_file)
         self.assertEqual('foo bar', as_string(c.loops[3].val(0, 2)))
 
+
 class TestLoopsMove(unittest.TestCase):
+    def setUp(self) -> None:
+        self.testcif = Path('tests/examples/1979688.cif').resolve()
+        # TODO: make tests where changes file is active:
+        Path('tests/examples/1979688-finalcif_changes.cif').unlink(missing_ok=True)
+        self.myapp = AppWindow(self.testcif, unit_test=True)
+        self.myapp.running_inside_unit_test = True
+        self.myapp.hide()  # For full screen view
+        self.myapp.ui.LoopsPushButton.click()
+
     def tearDown(self) -> None:
         self.myapp.cif.finalcif_file.unlink(missing_ok=True)
         self.myapp.close()
+        Path('tests/examples/1979688-finalcif_changes.cif').unlink(missing_ok=True)
 
     def get_index_of(self, loopkey: str = ''):
         tabw: QTabWidget = self.myapp.ui.LoopsTabWidget
@@ -94,13 +107,6 @@ def get_index_of(self, loopkey: str = ''):
                 tab = -1
         return tab
 
-    def setUp(self) -> None:
-        self.testcif = Path('tests/examples/1979688.cif').resolve()
-        self.myapp = AppWindow(self.testcif, unit_test=True)
-        self.myapp.running_inside_unit_test = True
-        self.myapp.hide()  # For full screen view
-        self.myapp.ui.LoopsPushButton.click()
-
     def set_current_index_to_row_col(self, row, col, tab='Scattering'):
         view = self.myapp.ui.LoopsTabWidget.widget(self.get_index_of(tab))
         index = view.model().index(row, col)
@@ -165,7 +171,6 @@ def test_move_row_down_from_end_save_and_load_again(self):
         self.assertEqual('H', as_string(c.loops[3].val(1, 0)))
         self.assertEqual('O', as_string(c.loops[3].val(2, 0)))
 
-
     def test_move_row_up_from_middle(self):
         view = self.set_current_index_to_row_col(1, 0)
         view._row_up(None)
@@ -196,4 +201,4 @@ def test_move_row_up_from_start_save_and_load_again(self):
         c = CifContainer(self.myapp.cif.finalcif_file)
         self.assertEqual('C', as_string(c.loops[3].val(0, 0)))
         self.assertEqual('H', as_string(c.loops[3].val(1, 0)))
-        self.assertEqual('O', as_string(c.loops[3].val(2, 0)))
\ No newline at end of file
+        self.assertEqual('O', as_string(c.loops[3].val(2, 0)))
diff --git a/tests/test_main_table.py b/tests/test_main_table.py
index 8ecaa1e1..c48f5bfe 100644
--- a/tests/test_main_table.py
+++ b/tests/test_main_table.py
@@ -4,7 +4,6 @@
 #   this notice you can do whatever you want with this stuff. If we meet some day,
 #   and you think this stuff is worth it, you can buy me a beer in return.
 #   ----------------------------------------------------------------------------
-import os
 import unittest
 from pathlib import Path
 
@@ -20,14 +19,17 @@ class TestMainTableFieldBehavior(unittest.TestCase):
 
     def setUp(self) -> None:
         self.testcif = Path('tests/examples/1979688.cif').absolute()
+        Path('tests/examples/1979688-finalcif_changes.cif').unlink(missing_ok=True)
         self.myapp = AppWindow(self.testcif, unit_test=True)
         self.myapp.running_inside_unit_test = True
         self.myapp.hide()  # For full screen view
         self.myapp.settings.empty_deleted_list()
+        self.myapp.ui.trackChangesCifCheckBox.setChecked(False)
 
     def tearDown(self) -> None:
         self.myapp.cif.finalcif_file.unlink(missing_ok=True)
         self.myapp.close()
+        Path('tests/examples/1979688-finalcif_changes.cif').unlink(missing_ok=True)
 
     def key_row(self, key: str) -> int:
         return self.myapp.ui.cif_main_table.row_from_key(key)
@@ -57,15 +59,13 @@ def test_delete_row(self):
         self.assertEqual(130, self.myapp.ui.cif_main_table.rowCount())
 
     def test_delete_and_reappear(self):
+        self.assertEqual(131, self.myapp.ui.cif_main_table.rowCount())
         self.myapp.ui.cif_main_table.delete_row(
             self.myapp.ui.cif_main_table.row_from_key('_atom_sites_solution_primary'))
-        # cline count stays the same:
-        self.assertEqual(131, self.myapp.ui.cif_main_table.rowCount())
-        self.assertEqual('?', self.cell_text('_atom_sites_solution_primary', COL_CIF))
-        # method comes from solution program now:
-        self.assertEqual('direct', self.cell_text('_atom_sites_solution_primary', COL_DATA))
-        # This is an essential key, it reappears after reload:
-        self.assertEqual(0, self.key_row('_atom_sites_solution_primary'))
+        # One less than before:
+        self.assertEqual(130, self.myapp.ui.cif_main_table.rowCount())
+        # Line is deleted:
+        self.assertFalse('_atom_sites_solution_primary' in self.myapp.ui.cif_main_table.vheaderitems)
 
     def test_get_text_by_key(self):
         self.assertEqual('geom', self.cell_text('_atom_sites_solution_hydrogens', COL_CIF))
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 54104201..f3bb3123 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -54,6 +54,11 @@ def test_strip_finalcif(self):
         self.assertEqual('406-0308', stripped)
         self.assertEqual('foobar', strip_finalcif_of_name('foobar'))
 
+    def test_strip_finalcif_till_end(self):
+        self.assertEqual('cu_BruecknerJK_153F40_0m', strip_finalcif_of_name('cu_BruecknerJK_153F40_0m-finalcif'))
+        self.assertEqual('cu_BruecknerJK_153F40_0m-finalcif_changes', strip_finalcif_of_name('cu_BruecknerJK_153F40_0m-finalcif_changes'))
+        self.assertEqual('cu_BruecknerJK_153F40_0m', strip_finalcif_of_name('cu_BruecknerJK_153F40_0m-finalcif_changes', till_name_ends=True))
+
     def test_isnumeric_true(self):
         self.assertEqual(True, isnumeric('1.234'))
         self.assertEqual(True, isnumeric('234'))
diff --git a/tests/test_workfolder.py b/tests/test_workfolder.py
index ddeaaf7d..91447f7c 100644
--- a/tests/test_workfolder.py
+++ b/tests/test_workfolder.py
@@ -44,8 +44,8 @@ def setUp(self) -> None:
         self.myapp.hide()
         self.myapp.setWindowIcon(QIcon('./icon/multitable.png'))
         self.myapp.setWindowTitle('FinalCif v{}'.format(VERSION))
-        Path('foo.cif').unlink(missing_ok=True)
-        Path('cu_BruecknerJK_153F40_0m-finalcif.cif').unlink(missing_ok=True)
+        Path('tests/examples/work/foo.cif').unlink(missing_ok=True)
+        Path('tests/examples/work/cu_BruecknerJK_153F40_0m-finalcif.cif').unlink(missing_ok=True)
 
     def tearDown(self) -> None:
         Path('foo.cif').unlink(missing_ok=True)
@@ -62,6 +62,8 @@ class TestWorkfolder(unittest.TestCase):
 
     def setUp(self) -> None:
         self.testcif = Path('tests/examples/work/cu_BruecknerJK_153F40_0m.cif').resolve()
+        # TODO: Adapt this to the bahavior with the changes file:
+        Path('tests/examples/work/cu_BruecknerJK_153F40_0m-finalcif_changes.cif').unlink(missing_ok=True)
         self.myapp = AppWindow(self.testcif, unit_test=True)
         self.myapp.equipment.import_equipment_from_file('test-data/Crystallographer_Details.cif')
         self.myapp.running_inside_unit_test = True
@@ -74,6 +76,7 @@ def tearDown(self) -> None:
         self.testcif.with_suffix('.lst').unlink(missing_ok=True)
         self.testcif.with_suffix('.2fcf').unlink(missing_ok=True)
         Path('tests/testcif_file.cif').unlink(missing_ok=True)
+        Path('tests/examples/work/cu_BruecknerJK_153F40_0m-finalcif_changes.cif').unlink(missing_ok=True)
         self.myapp.close()
 
     def key_row(self, key: str) -> int: