finalcif 169__tar.gz → 170__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {finalcif-169 → finalcif-170}/Finalcif_installer_win.spec +1 -1
- {finalcif-169 → finalcif-170}/PKG-INFO +1 -1
- finalcif-170/finalcif/__init__.py +3 -0
- {finalcif-169 → finalcif-170}/finalcif/appwindow.py +57 -20
- {finalcif-169 → finalcif-170}/finalcif/cif/cif_file_io.py +18 -13
- {finalcif-169 → finalcif-170}/finalcif/equip_property/author_loop_templates.py +2 -1
- {finalcif-169 → finalcif-170}/finalcif/equip_property/equipment.py +2 -1
- {finalcif-169 → finalcif-170}/finalcif/equip_property/properties.py +3 -2
- {finalcif-169 → finalcif-170}/finalcif/finalcif_start.py +3 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/cif_table_view.py +2 -1
- finalcif-170/finalcif/gui/dialogs.py +447 -0
- finalcif-170/finalcif/gui/file_editor.py +355 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/import_selector.py +48 -29
- {finalcif-169 → finalcif-170}/finalcif/gui/import_selector_ui.py +13 -3
- {finalcif-169 → finalcif-170}/finalcif/gui/import_selector_ui.ui +10 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/loops.py +17 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/spell_check_edit.py +3 -1
- {finalcif-169 → finalcif-170}/finalcif/gui/squeeze_dialog.py +11 -1
- {finalcif-169 → finalcif-170}/finalcif/gui/syntax_highlighter.py +34 -14
- finalcif-170/finalcif/gui/timers.py +21 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/vzs_viewer.py +9 -3
- {finalcif-169 → finalcif-170}/finalcif/tools/misc.py +9 -0
- finalcif-170/finalcif/tools/selfupdate.py +348 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/settings.py +50 -14
- {finalcif-169 → finalcif-170}/uv.lock +42 -42
- finalcif-169/finalcif/__init__.py +0 -3
- finalcif-169/finalcif/gui/dialogs.py +0 -268
- finalcif-169/finalcif/gui/file_editor.py +0 -123
- finalcif-169/update.exe +0 -0
- {finalcif-169 → finalcif-170}/.gitattributes +0 -0
- {finalcif-169 → finalcif-170}/.githooks/pre-push +0 -0
- {finalcif-169 → finalcif-170}/.gitignore +0 -0
- {finalcif-169 → finalcif-170}/.python-version +0 -0
- {finalcif-169 → finalcif-170}/.ruff.toml +0 -0
- {finalcif-169 → finalcif-170}/.run/Make Documentation MAC.run.xml +0 -0
- {finalcif-169 → finalcif-170}/.run/compile_ui_files.run.xml +0 -0
- {finalcif-169 → finalcif-170}/.run/make documentation Windows.run.xml +0 -0
- {finalcif-169 → finalcif-170}/AGENTS.md +0 -0
- {finalcif-169 → finalcif-170}/CODE_OF_CONDUCT.md +0 -0
- {finalcif-169 → finalcif-170}/CONTRIBUTING.md +0 -0
- {finalcif-169 → finalcif-170}/Finalcif_linux_onefile.spec +0 -0
- {finalcif-169 → finalcif-170}/Finalcif_mac.spec +0 -0
- {finalcif-169 → finalcif-170}/LICENSE +0 -0
- {finalcif-169 → finalcif-170}/README.md +0 -0
- {finalcif-169 → finalcif-170}/finalcif/app_path.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/all_cif_dicts.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/atoms.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/checkcif/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/checkcif/checkcif.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cif_dict_foo.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cif_keyword_mapping.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cif_order.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cod/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cod/deposit.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cod/deposit_check.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cod/deposition_list.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cod/doi.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cod/upload.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/cod/website_parser.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/core_dict.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/hkl.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/modulation_dict.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/powder_dict.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/reference.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/restraints_dict.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/text.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/twin_dict.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/cif/vrf_entry.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/ciforder/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/ciforder/order.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/ciforder/order_ui.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/ciforder/order_ui.ui +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/bruker_data.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/bruker_frame.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/ccdc_mail.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/data.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/p4p_reader.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/sadabs.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/saint.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/shelx_lst.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/datafiles/utils.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/displaymol/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/displaymol/vtk_molecule.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/equip_property/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/equip_property/tools.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/block_combobox.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/checkcif_browser.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/cif_table_model.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/combobox.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/custom_classes.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/edit_button.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/equipmenttable.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/finalcif_gui_ui.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/finalcif_gui_ui.ui +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/loop_creator.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/loop_creator_ui.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/loop_creator_ui.ui +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/mainstackwidget.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/mixins.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/new_key_dialog.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/new_key_dialog_ui.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/new_key_dialog_ui.ui +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/plaintextedit.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/playground.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/propertytable.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/shelx_navigation.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/single_line_textedit.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/text_templates_ui.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/text_templates_ui.ui +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/text_value_editor.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/validators.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/gui/vrf_classes.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/icon/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/icon/finalcif.png +0 -0
- {finalcif-169 → finalcif-170}/finalcif/icon/finalcif2.ico +0 -0
- {finalcif-169 → finalcif-170}/finalcif/icon/finalcif2.png +0 -0
- {finalcif-169 → finalcif-170}/finalcif/icon/multitable.ico +0 -0
- {finalcif-169 → finalcif-170}/finalcif/icon/multitable.png +0 -0
- {finalcif-169 → finalcif-170}/finalcif/icon/multitable.xcf +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/archive_report.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/gui/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/gui/mainwindow.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/gui/mainwindow.ui +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/mtools.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/references.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/report_text.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/symm.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/tables.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/report/templated_report.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/bootstrap/bootstrap.min.css +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/machines/D8_VENTURE.cif +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/mathml2omml.xsl +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/report.tex +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/report.tmpl +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/report2.tex +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/report_default.docx +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/template1.docx +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/template_for_multitable.docx +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/template_text.docx +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/template_without_text.docx +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/templates.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/FakePlasTeX/FakeContext.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/FakePlasTeX/FakeTokenizer.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/FakePlasTeX/README.md +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/FakePlasTeX/TokenizerPassThru.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/LICENSE +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/u2l.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/unicode-math-table.tex +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/unicode2latex/unicode-math-xetex.sty +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/xsl/convert.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/xsl/xmltohtml.xsl +0 -0
- {finalcif-169 → finalcif-170}/finalcif/template/xsl/xmltolatex.xsl +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/__init__.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/chemparse.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/download.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/dsrmath.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/formal_charge.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/options.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/platon.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/pupdate.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/shred.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/space_groups.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/spgr_format.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/squeeze.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/statusbar.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/sumformula.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif/tools/z_from_packing.py +0 -0
- {finalcif-169 → finalcif-170}/finalcif.exe +0 -0
- {finalcif-169 → finalcif-170}/platon/README.txt +0 -0
- {finalcif-169 → finalcif-170}/platon/compile_platon.bat +0 -0
- {finalcif-169 → finalcif-170}/platon/platon_special.exe +0 -0
- {finalcif-169 → finalcif-170}/platon/platon_special.f +0 -0
- {finalcif-169 → finalcif-170}/pylock.toml +0 -0
- {finalcif-169 → finalcif-170}/pyproject.toml +0 -0
- {finalcif-169 → finalcif-170}/run_and_capture.py +0 -0
- {finalcif-169 → finalcif-170}/run_finalcif +0 -0
- {finalcif-169 → finalcif-170}/run_finalcif.bat +0 -0
- {finalcif-169 → finalcif-170}/screenshots/finalcif_checkcif.png +0 -0
- {finalcif-169 → finalcif-170}/screenshots/finalcif_details.png +0 -0
- {finalcif-169 → finalcif-170}/screenshots/finalcif_loops.png +0 -0
- {finalcif-169 → finalcif-170}/screenshots/finalcif_loops2.png +0 -0
- {finalcif-169 → finalcif-170}/screenshots/finalcif_main.png +0 -0
- {finalcif-169 → finalcif-170}/screenshots/finalcif_report.png +0 -0
- {finalcif-169 → finalcif-170}/screenshots/finalcif_responses.png +0 -0
- {finalcif-169 → finalcif-170}/screenshots/loops_column_buttons.png +0 -0
- {finalcif-169 → finalcif-170}/work/compare_z_platon.py +0 -0
- {finalcif-169 → finalcif-170}/work/diagnose_1519506.py +0 -0
- {finalcif-169 → finalcif-170}/work/diagnose_z.py +0 -0
- {finalcif-169 → finalcif-170}/work/investigate_failures.py +0 -0
- {finalcif-169 → finalcif-170}/work/validate_cod.py +0 -0
- {finalcif-169 → finalcif-170}/work/validate_zprime.py +0 -0
|
@@ -9,7 +9,7 @@ site_packages = next(p for p in sys.path if 'site-packages' in p)
|
|
|
9
9
|
|
|
10
10
|
a = Analysis(['finalcif/finalcif_start.py'],
|
|
11
11
|
pathex=['finalcif'],
|
|
12
|
-
binaries=[
|
|
12
|
+
binaries=[],
|
|
13
13
|
datas=[('finalcif/gui', 'gui'),
|
|
14
14
|
(path.join(site_packages, "docx", "templates"), 'finalcif/docx/templates'),
|
|
15
15
|
('finalcif/template', 'template'), ('finalcif/icon', 'icon'),
|
|
@@ -70,13 +70,15 @@ from finalcif.gui.plaintextedit import MyQPlainTextEdit
|
|
|
70
70
|
from finalcif.gui.validators import calculated_z_validator
|
|
71
71
|
from finalcif.gui.checkcif_browser import CheckCifBrowser
|
|
72
72
|
from finalcif.gui.text_value_editor import MyTextTemplateEdit, TextEditItem
|
|
73
|
+
from finalcif.gui.timers import single_shot
|
|
73
74
|
from finalcif.cif.vrf_entry import VRFEntry
|
|
74
75
|
from finalcif.gui.vrf_classes import MyVRFContainer
|
|
75
76
|
from finalcif.template.templates import ReportTemplates
|
|
76
77
|
from finalcif.tools.download import MyDownloader
|
|
77
78
|
from finalcif.tools.dsrmath import my_isnumeric
|
|
78
79
|
from finalcif.tools.misc import (next_path, celltxt, to_float, is_database_number,
|
|
79
|
-
open_file, strip_finalcif_of_name, file_age_in_days, open_in_text_editor
|
|
80
|
+
open_file, strip_finalcif_of_name, file_age_in_days, open_in_text_editor,
|
|
81
|
+
running_inside_unit_test as is_unit_test)
|
|
80
82
|
from finalcif.tools.options import Options
|
|
81
83
|
from finalcif.tools.platon import PlatonRunner
|
|
82
84
|
from finalcif.tools.settings import FinalCifSettings
|
|
@@ -155,6 +157,7 @@ class _StructureFactorReportThread(QtCore.QThread):
|
|
|
155
157
|
|
|
156
158
|
|
|
157
159
|
class AppWindow(QMainWindow):
|
|
160
|
+
thread_shutdown_timeout_ms = 10_000
|
|
158
161
|
|
|
159
162
|
def __init__(self, file: Path | None = None):
|
|
160
163
|
super().__init__()
|
|
@@ -163,6 +166,7 @@ class AppWindow(QMainWindow):
|
|
|
163
166
|
self.thread_version = None
|
|
164
167
|
self.worker = None
|
|
165
168
|
self._z_thread: _ZEstimatorThread | None = None
|
|
169
|
+
self.structure_factor_thread: _StructureFactorReportThread | None = None
|
|
166
170
|
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose)
|
|
167
171
|
# This prevents some things to happen during unit tests:
|
|
168
172
|
# Open of target dir of shred cif,
|
|
@@ -269,9 +273,9 @@ class AppWindow(QMainWindow):
|
|
|
269
273
|
|
|
270
274
|
@property
|
|
271
275
|
def running_inside_unit_test(self):
|
|
272
|
-
if
|
|
276
|
+
if is_unit_test():
|
|
273
277
|
if DEBUG:
|
|
274
|
-
print(f'pytest process running: {os.environ
|
|
278
|
+
print(f'pytest process running: {os.environ.get("PYTEST_CURRENT_TEST")}')
|
|
275
279
|
return True
|
|
276
280
|
return False
|
|
277
281
|
|
|
@@ -540,8 +544,8 @@ class AppWindow(QMainWindow):
|
|
|
540
544
|
|
|
541
545
|
def set_video_image_for_report(self):
|
|
542
546
|
image_filename = self.cif.finalcif_file_prefixed(prefix='', suffix='_video-finalcif.png')
|
|
543
|
-
self.video.save_image(image_filename)
|
|
544
|
-
|
|
547
|
+
if self.video.save_image(image_filename):
|
|
548
|
+
self.options.video_image = image_filename
|
|
545
549
|
|
|
546
550
|
def _select_crystal_video(self, video_file: Path | None = None) -> None:
|
|
547
551
|
if video_file is None:
|
|
@@ -875,8 +879,26 @@ class AppWindow(QMainWindow):
|
|
|
875
879
|
with suppress(Exception):
|
|
876
880
|
self._savesize()
|
|
877
881
|
self.settings.flush()
|
|
882
|
+
self._stop_background_threads()
|
|
878
883
|
super().closeEvent(event)
|
|
879
884
|
|
|
885
|
+
def _stop_background_threads(self) -> None:
|
|
886
|
+
"""Finish all worker threads before Qt destroys them together with this window.
|
|
887
|
+
|
|
888
|
+
Qt aborts the whole process when a running QThread is deleted. findChildren()
|
|
889
|
+
is used instead of the individual attributes because a superseded worker may
|
|
890
|
+
still run after its attribute was cleared.
|
|
891
|
+
"""
|
|
892
|
+
for thread in self.findChildren(QtCore.QThread):
|
|
893
|
+
if not thread.isRunning():
|
|
894
|
+
continue
|
|
895
|
+
# Prevent a result from being delivered into the dying window.
|
|
896
|
+
thread.blockSignals(True)
|
|
897
|
+
thread.quit()
|
|
898
|
+
if not thread.wait(self.thread_shutdown_timeout_ms):
|
|
899
|
+
thread.terminate()
|
|
900
|
+
thread.wait()
|
|
901
|
+
|
|
880
902
|
def show_help(self) -> None:
|
|
881
903
|
QtGui.QDesktopServices.openUrl(QtCore.QUrl('https://dkratzert.de/files/finalcif/docs/'))
|
|
882
904
|
|
|
@@ -916,7 +938,27 @@ class AppWindow(QMainWindow):
|
|
|
916
938
|
dialog = SqueezeSolventDialog(cif=self.cif, mode=mode, parent=self)
|
|
917
939
|
if dialog._cancelled:
|
|
918
940
|
return False
|
|
919
|
-
|
|
941
|
+
accepted = bool(dialog.exec())
|
|
942
|
+
if accepted:
|
|
943
|
+
self._refresh_after_squeeze_dialog(dialog)
|
|
944
|
+
return accepted
|
|
945
|
+
|
|
946
|
+
def _refresh_after_squeeze_dialog(self, dialog: SqueezeSolventDialog) -> None:
|
|
947
|
+
"""
|
|
948
|
+
Show the values written by the solvent dialog without leaving the current page.
|
|
949
|
+
"""
|
|
950
|
+
self._update_squeeze_details_row(dialog.details_key, dialog.details_text)
|
|
951
|
+
if self.ui.MainStackedWidget.on_loops_page():
|
|
952
|
+
self.ui.loops_page.reload()
|
|
953
|
+
|
|
954
|
+
def _update_squeeze_details_row(self, key: str, text: str) -> None:
|
|
955
|
+
if not self.ui.cif_main_table.rowCount():
|
|
956
|
+
return
|
|
957
|
+
if not self.ui.cif_main_table.has_key(key):
|
|
958
|
+
if not text:
|
|
959
|
+
return
|
|
960
|
+
self.add_row(key=key, value=text, at_start=True)
|
|
961
|
+
self.ui.cif_main_table.setText(key=key, column=Column.EDIT, txt=text)
|
|
920
962
|
|
|
921
963
|
def _ccdc_deposit(self) -> None:
|
|
922
964
|
"""
|
|
@@ -1727,8 +1769,7 @@ class AppWindow(QMainWindow):
|
|
|
1727
1769
|
fixfont.setPointSize(fixfont.pointSize() + 2)
|
|
1728
1770
|
doc.setDefaultFont(fixfont)
|
|
1729
1771
|
final_textedit.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap)
|
|
1730
|
-
final_textedit.
|
|
1731
|
-
QtCore.QTimer().singleShot(0, lambda: final_textedit.highlighter.setDocument(doc))
|
|
1772
|
+
final_textedit.set_cif_text(self.cif.as_saved_string())
|
|
1732
1773
|
|
|
1733
1774
|
def import_additional_cif(self, filename: str):
|
|
1734
1775
|
"""
|
|
@@ -1818,18 +1859,16 @@ class AppWindow(QMainWindow):
|
|
|
1818
1859
|
if not self.cif.chars_ok:
|
|
1819
1860
|
self.warn_about_bad_cif()
|
|
1820
1861
|
# Do this only when sure we can load the file:
|
|
1821
|
-
|
|
1862
|
+
single_shot(self, 0, lambda: self.save_current_recent_files_list(filepath))
|
|
1822
1863
|
self._load_block(block, load_changes=load_changes)
|
|
1823
1864
|
self.add_data_names_to_combobox()
|
|
1824
1865
|
self.ui.datanameComboBox.setCurrentIndex(block)
|
|
1825
1866
|
self.ui.datanameComboBox.blockSignals(False)
|
|
1826
|
-
|
|
1867
|
+
single_shot(self, 500, self.ui.cif_main_table.resizeRowsToContents)
|
|
1827
1868
|
if self.cif.is_multi_cif:
|
|
1828
1869
|
self._flash_block_combobox()
|
|
1829
1870
|
self.cif.set_order_keys(self.ui.cifOrderWidget.order_keys)
|
|
1830
|
-
|
|
1831
|
-
# Enable to find widgets without parent:
|
|
1832
|
-
# QtCore.QTimer(self).singleShot(1000, self.find_widgets_without_parent)
|
|
1871
|
+
single_shot(self, 0, self._find_video)
|
|
1833
1872
|
|
|
1834
1873
|
def _find_video(self) -> None:
|
|
1835
1874
|
self.video.reset()
|
|
@@ -1853,8 +1892,8 @@ class AppWindow(QMainWindow):
|
|
|
1853
1892
|
pal.setColor(QtGui.QPalette.ColorRole.Base, light_blue)
|
|
1854
1893
|
self.ui.datanameComboBox.setAutoFillBackground(True)
|
|
1855
1894
|
# short after start, because window size is not finished before:
|
|
1856
|
-
|
|
1857
|
-
|
|
1895
|
+
single_shot(self, 1500, lambda: self.ui.datanameComboBox.setPalette(pal))
|
|
1896
|
+
single_shot(self, 2600, lambda: self.ui.datanameComboBox.setPalette(orig_pal))
|
|
1858
1897
|
|
|
1859
1898
|
def add_data_names_to_combobox(self) -> None:
|
|
1860
1899
|
self.ui.datanameComboBox.clear()
|
|
@@ -1932,8 +1971,7 @@ class AppWindow(QMainWindow):
|
|
|
1932
1971
|
self.show_residuals()
|
|
1933
1972
|
self.redraw_molecule()
|
|
1934
1973
|
self._update_z_label()
|
|
1935
|
-
|
|
1936
|
-
t.singleShot(1000, self.check_cecksums)
|
|
1974
|
+
single_shot(self, 1000, self.check_cecksums)
|
|
1937
1975
|
|
|
1938
1976
|
def _delete_current_block(self, index: int) -> None:
|
|
1939
1977
|
self.cif.delete_block(index)
|
|
@@ -2132,8 +2170,7 @@ class AppWindow(QMainWindow):
|
|
|
2132
2170
|
self.ui.peakLineEdit.setText("{} / {}".format(peak, self.cif['_refine_diff_density_min']))
|
|
2133
2171
|
self._show_shelx_file()
|
|
2134
2172
|
try:
|
|
2135
|
-
|
|
2136
|
-
# threading.Thread(target=self.view_molecule).start()
|
|
2173
|
+
single_shot(self, 0, lambda: self.view_molecule(reset_view=True))
|
|
2137
2174
|
except Exception:
|
|
2138
2175
|
print('Molecule view crashed!')
|
|
2139
2176
|
|
|
@@ -2577,7 +2614,7 @@ class AppWindow(QMainWindow):
|
|
|
2577
2614
|
table.clearSelection()
|
|
2578
2615
|
|
|
2579
2616
|
def check_cecksums(self):
|
|
2580
|
-
if
|
|
2617
|
+
if self.running_inside_unit_test:
|
|
2581
2618
|
return
|
|
2582
2619
|
if not self.cif.test_res_checksum():
|
|
2583
2620
|
show_res_checksum_warning(parent=self)
|
|
@@ -386,6 +386,20 @@ class CifContainer:
|
|
|
386
386
|
else:
|
|
387
387
|
self.block.set_pair(key, quote(txt))
|
|
388
388
|
|
|
389
|
+
def write_options(self) -> gemmi.cif.WriteOptions:
|
|
390
|
+
"""The gemmi write options used to save and to display the CIF."""
|
|
391
|
+
options = gemmi.cif.WriteOptions()
|
|
392
|
+
options.prefer_pairs = False
|
|
393
|
+
options.compact = False
|
|
394
|
+
options.align_pairs = 33
|
|
395
|
+
options.align_loops = 15
|
|
396
|
+
options.misuse_hash = False
|
|
397
|
+
return options
|
|
398
|
+
|
|
399
|
+
def as_saved_string(self) -> str:
|
|
400
|
+
"""The CIF text exactly as :meth:`save` writes it to disk."""
|
|
401
|
+
return self.doc.as_string(options=self.write_options())
|
|
402
|
+
|
|
389
403
|
def save(self, filename: Path | None = None) -> None:
|
|
390
404
|
"""
|
|
391
405
|
Saves the current cif file. It uses the '[basename]-finalcif.cif' suffix by default.
|
|
@@ -400,16 +414,7 @@ class CifContainer:
|
|
|
400
414
|
raise PermissionError(f'Failed to open {filename.resolve()} for writing: Operation not permitted')
|
|
401
415
|
self.order_cif_keys()
|
|
402
416
|
print('Saving CIF to', Path(filename).resolve())
|
|
403
|
-
|
|
404
|
-
options = gemmi.cif.WriteOptions()
|
|
405
|
-
options.prefer_pairs = False
|
|
406
|
-
options.compact = False
|
|
407
|
-
options.align_pairs = 33
|
|
408
|
-
options.align_loops = 15
|
|
409
|
-
options.misuse_hash = False
|
|
410
|
-
self.doc.write_file(str(filename), options=options)
|
|
411
|
-
else:
|
|
412
|
-
self.doc.write_file(str(filename), gemmi.cif.Style.Indent35)
|
|
417
|
+
self.doc.write_file(str(filename), options=self.write_options())
|
|
413
418
|
|
|
414
419
|
def is_writable(self, filepath: Path | str) -> bool:
|
|
415
420
|
filepath = Path(filepath)
|
|
@@ -973,9 +978,9 @@ class CifContainer:
|
|
|
973
978
|
publ_loop = self.block.find_loop('_geom_angle_publ_flag') or len(label1) * ['?']
|
|
974
979
|
angle = namedtuple('angle', ('label1', 'label2', 'label3', 'angle_val', 'symm1', 'symm2'))
|
|
975
980
|
for label1, label2, label3, angle_val, symm1, symm2, publ in (
|
|
976
|
-
|
|
981
|
+
zip(label1, label2, label3, angle_val, symm1, symm2, publ_loop, strict=False)):
|
|
977
982
|
if ((without_H and (self.ishydrogen(label1) or self.ishydrogen(label2) or self.ishydrogen(label3))) or
|
|
978
|
-
|
|
983
|
+
self.yes_not_set(publ)):
|
|
979
984
|
continue
|
|
980
985
|
else:
|
|
981
986
|
yield angle(label1=label1, label2=label2, label3=label3, angle_val=angle_val,
|
|
@@ -1049,7 +1054,7 @@ class CifContainer:
|
|
|
1049
1054
|
hydr = namedtuple('HydrogenBond', ('label_d', 'label_h', 'label_a', 'dist_dh', 'dist_ha', 'dist_da',
|
|
1050
1055
|
'angle_dha', 'symm'))
|
|
1051
1056
|
for label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ in (
|
|
1052
|
-
|
|
1057
|
+
zip(label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ_loop, strict=False)):
|
|
1053
1058
|
if self.yes_not_set(publ):
|
|
1054
1059
|
continue
|
|
1055
1060
|
if self.picometer:
|
|
@@ -22,6 +22,7 @@ from finalcif.cif.text import utf8_to_str, quote, retranslate_delimiter, string_
|
|
|
22
22
|
from finalcif.equip_property.tools import read_document_from_cif_file
|
|
23
23
|
from finalcif.gui.dialogs import cif_file_save_dialog, show_general_warning, cif_file_open_dialog
|
|
24
24
|
from finalcif.gui.finalcif_gui_ui import Ui_FinalCifWindow
|
|
25
|
+
from finalcif.gui.timers import single_shot
|
|
25
26
|
from finalcif.tools.misc import grouper
|
|
26
27
|
from finalcif.tools.settings import FinalCifSettings
|
|
27
28
|
|
|
@@ -452,7 +453,7 @@ class AuthorLoops:
|
|
|
452
453
|
self._rename_old_name = item.text()
|
|
453
454
|
# Defer editItem() to the next event-loop tick so that all
|
|
454
455
|
# menu-close events are processed before Qt starts the editor.
|
|
455
|
-
|
|
456
|
+
single_shot(listw, 0, lambda: listw.editItem(item))
|
|
456
457
|
|
|
457
458
|
menu.triggered.connect(_on_triggered)
|
|
458
459
|
menu.popup(listw.viewport().mapToGlobal(pos))
|
|
@@ -14,6 +14,7 @@ from finalcif.cif.text import retranslate_delimiter, string_to_utf8
|
|
|
14
14
|
from finalcif.equip_property.tools import read_document_from_cif_file
|
|
15
15
|
from finalcif.gui.custom_classes import Column, light_green
|
|
16
16
|
from finalcif.gui.dialogs import show_general_warning, cif_file_open_dialog, cif_file_save_dialog
|
|
17
|
+
from finalcif.gui.timers import single_shot
|
|
17
18
|
from finalcif.tools import misc
|
|
18
19
|
from finalcif.tools.misc import include_equipment_imports
|
|
19
20
|
from finalcif.tools.settings import FinalCifSettings
|
|
@@ -94,7 +95,7 @@ class Equipment:
|
|
|
94
95
|
self._rename_old_name = item.text()
|
|
95
96
|
# Defer editItem() to the next event-loop tick so that all
|
|
96
97
|
# menu-close events are processed before Qt starts the editor.
|
|
97
|
-
|
|
98
|
+
single_shot(listw, 0, lambda: listw.editItem(item))
|
|
98
99
|
|
|
99
100
|
menu.triggered.connect(_on_triggered)
|
|
100
101
|
menu.popup(listw.viewport().mapToGlobal(pos))
|
|
@@ -14,6 +14,7 @@ from finalcif.cif.text import retranslate_delimiter, utf8_to_str
|
|
|
14
14
|
from finalcif.equip_property.tools import read_document_from_cif_file
|
|
15
15
|
from finalcif.gui.dialogs import cif_file_open_dialog, show_general_warning, cif_file_save_dialog
|
|
16
16
|
from finalcif.gui.plaintextedit import PlainTextEditTemplate
|
|
17
|
+
from finalcif.gui.timers import single_shot
|
|
17
18
|
from finalcif.tools import misc
|
|
18
19
|
from finalcif.tools.settings import FinalCifSettings
|
|
19
20
|
|
|
@@ -72,7 +73,7 @@ class Properties(QtCore.QObject):
|
|
|
72
73
|
self.lb.setText(f'key {key} already exists')
|
|
73
74
|
self.lb.move(self.app.ui.cifKeywordLineEdit.mapToGlobal(QtCore.QPoint(15, 25)))
|
|
74
75
|
self.lb.show()
|
|
75
|
-
|
|
76
|
+
single_shot(self.lb, 5000, self.hide_label)
|
|
76
77
|
else:
|
|
77
78
|
self.app.ui.SavePropertiesButton.setEnabled(True)
|
|
78
79
|
self.lb.hide()
|
|
@@ -118,7 +119,7 @@ class Properties(QtCore.QObject):
|
|
|
118
119
|
self._rename_old_name = item.text()
|
|
119
120
|
# Defer editItem() to the next event-loop tick so that all
|
|
120
121
|
# menu-close events are processed before Qt starts the editor.
|
|
121
|
-
|
|
122
|
+
single_shot(listw, 0, lambda: listw.editItem(item))
|
|
122
123
|
|
|
123
124
|
menu.triggered.connect(_on_triggered)
|
|
124
125
|
menu.popup(listw.viewport().mapToGlobal(pos))
|
|
@@ -17,6 +17,7 @@ from finalcif import VERSION
|
|
|
17
17
|
from finalcif.app_path import application_path
|
|
18
18
|
from finalcif.appwindow import AppWindow, DEBUG, app
|
|
19
19
|
from finalcif.gui.dialogs import show_bug_found_warning, show_general_warning
|
|
20
|
+
from finalcif.tools.selfupdate import create_running_mutex
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def my_exception_hook(exctype: type[BaseException], value: BaseException, error_traceback: traceback,
|
|
@@ -73,6 +74,8 @@ def my_exception_hook(exctype: type[BaseException], value: BaseException, error_
|
|
|
73
74
|
def main():
|
|
74
75
|
if not DEBUG:
|
|
75
76
|
sys.excepthook = my_exception_hook
|
|
77
|
+
# The installer (AppMutex) must not overwrite the files of a running FinalCif:
|
|
78
|
+
create_running_mutex()
|
|
76
79
|
# windows_style = QStyleFactory.create('Fusion')
|
|
77
80
|
# app.setStyle(windows_style)
|
|
78
81
|
file = None
|
|
@@ -15,6 +15,7 @@ from finalcif.gui.cif_table_model import CifTableModel, Column, blue, CifRowData
|
|
|
15
15
|
from finalcif.gui.combobox import MyComboBox
|
|
16
16
|
from finalcif.gui.dialogs import show_keyword_help
|
|
17
17
|
from finalcif.gui.plaintextedit import MyQPlainTextEdit
|
|
18
|
+
from finalcif.gui.timers import single_shot
|
|
18
19
|
|
|
19
20
|
DEBUG = False
|
|
20
21
|
|
|
@@ -381,7 +382,7 @@ class CifTableView(QTableView):
|
|
|
381
382
|
return QObject.eventFilter(self, widget, event)
|
|
382
383
|
|
|
383
384
|
def resizeEvent(self, e: QtGui.QResizeEvent) -> None:
|
|
384
|
-
|
|
385
|
+
single_shot(self, 0, self.resizeRowsToContents)
|
|
385
386
|
super().resizeEvent(e)
|
|
386
387
|
|
|
387
388
|
|