finalcif 144__tar.gz → 147__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-144 → finalcif-147}/.gitignore +2 -0
- {finalcif-144 → finalcif-147}/PKG-INFO +4 -4
- finalcif-147/finalcif/__init__.py +2 -0
- {finalcif-144 → finalcif-147}/finalcif/appwindow.py +25 -4
- {finalcif-144 → finalcif-147}/finalcif/cif/cif_file_io.py +37 -16
- {finalcif-144 → finalcif-147}/finalcif/cif/cif_order.py +128 -0
- finalcif-147/finalcif/ciforder/order.py +229 -0
- finalcif-147/finalcif/ciforder/order_ui.py +103 -0
- finalcif-147/finalcif/ciforder/order_ui.ui +192 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/combobox.py +34 -3
- {finalcif-144 → finalcif-147}/finalcif/gui/custom_classes.py +15 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/finalcif_gui_ui.py +203 -158
- {finalcif-144 → finalcif-147}/finalcif/gui/finalcif_gui_ui.ui +255 -193
- {finalcif-144 → finalcif-147}/finalcif/gui/import_selector.py +9 -2
- {finalcif-144 → finalcif-147}/finalcif/gui/loops.py +2 -2
- {finalcif-144 → finalcif-147}/finalcif/gui/new_key_dialog.py +14 -4
- {finalcif-144 → finalcif-147}/finalcif/gui/new_key_dialog_ui.py +1 -1
- {finalcif-144 → finalcif-147}/finalcif/gui/new_key_dialog_ui.ui +1 -1
- {finalcif-144 → finalcif-147}/finalcif/gui/plaintextedit.py +25 -9
- {finalcif-144 → finalcif-147}/finalcif/report/templated_report.py +106 -30
- finalcif-147/finalcif/tools/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/misc.py +0 -129
- {finalcif-144 → finalcif-147}/finalcif/tools/space_groups.py +1 -1
- {finalcif-144 → finalcif-147}/finalcif/tools/sumformula.py +6 -6
- {finalcif-144 → finalcif-147}/requirements.txt +2 -2
- finalcif-144/finalcif/__init__.py +0 -2
- {finalcif-144 → finalcif-147}/.gitattributes +0 -0
- {finalcif-144 → finalcif-147}/.run/Make Documentation MAC.run.xml +0 -0
- {finalcif-144 → finalcif-147}/.run/compile_ui_files.run.xml +0 -0
- {finalcif-144 → finalcif-147}/.run/make documentation Windows.run.xml +0 -0
- {finalcif-144 → finalcif-147}/CODE_OF_CONDUCT.md +0 -0
- {finalcif-144 → finalcif-147}/CONTRIBUTING.md +0 -0
- {finalcif-144 → finalcif-147}/Finalcif_installer_win.spec +0 -0
- {finalcif-144 → finalcif-147}/Finalcif_linux_onefile.spec +0 -0
- {finalcif-144 → finalcif-147}/Finalcif_mac.spec +0 -0
- {finalcif-144 → finalcif-147}/Hydrogen_solution_type.cif +0 -0
- {finalcif-144 → finalcif-147}/LICENSE +0 -0
- {finalcif-144 → finalcif-147}/README.md +0 -0
- {finalcif-144 → finalcif-147}/finalcif/app_path.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/all_cif_dicts.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/atoms.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/checkcif/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/checkcif/checkcif.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/cif_dict_foo.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/cod/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/cod/deposit.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/cod/deposit_check.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/cod/deposition_list.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/cod/doi.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/cod/upload.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/cod/website_parser.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/core_dict.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/hkl.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/modulation_dict.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/powder_dict.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/reference.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/restraints_dict.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/text.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/cif/twin_dict.py +0 -0
- {finalcif-144/finalcif/datafiles → finalcif-147/finalcif/ciforder}/__init__.py +0 -0
- {finalcif-144/finalcif/displaymol → finalcif-147/finalcif/datafiles}/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/bruker_data.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/bruker_frame.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/ccdc_mail.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/data.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/p4p_reader.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/sadabs.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/saint.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/shelx_lst.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/datafiles/utils.py +0 -0
- {finalcif-144/finalcif/equip_property → finalcif-147/finalcif/displaymol}/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/displaymol/molecule2D.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/displaymol/sdm.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/displaymol/vtk_molecule.py +0 -0
- {finalcif-144/finalcif/gui → finalcif-147/finalcif/equip_property}/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/equip_property/author_loop_templates.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/equip_property/equipment.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/equip_property/properties.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/equip_property/tools.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/finalcif_start.py +0 -0
- {finalcif-144/finalcif/icon → finalcif-147/finalcif/gui}/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/block_combobox.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/dialogs.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/edit_button.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/equipmenttable.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/file_editor.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/import_selector_ui.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/import_selector_ui.ui +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/loop_creator.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/loop_creator_ui.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/loop_creator_ui.ui +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/mainstackwidget.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/mixins.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/playground.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/propertytable.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/spell_check_edit.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/text_templates_ui.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/text_templates_ui.ui +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/text_value_editor.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/validators.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/gui/vrf_classes.py +0 -0
- {finalcif-144/finalcif/report/gui → finalcif-147/finalcif/icon}/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/icon/finalcif.png +0 -0
- {finalcif-144 → finalcif-147}/finalcif/icon/finalcif2.ico +0 -0
- {finalcif-144 → finalcif-147}/finalcif/icon/finalcif2.png +0 -0
- {finalcif-144 → finalcif-147}/finalcif/icon/multitable.ico +0 -0
- {finalcif-144 → finalcif-147}/finalcif/icon/multitable.png +0 -0
- {finalcif-144 → finalcif-147}/finalcif/icon/multitable.xcf +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/archive_report.py +0 -0
- {finalcif-144/finalcif/template → finalcif-147/finalcif/report/gui}/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/gui/mainwindow.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/gui/mainwindow.ui +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/mtools.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/references.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/report_text.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/symm.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/report/tables.py +0 -0
- {finalcif-144/finalcif/tools → finalcif-147/finalcif/template}/__init__.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/bootstrap/bootstrap.min.css +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/machines/D8_VENTURE.cif +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/mathml2omml.xsl +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/report.tmpl +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/report_default.docx +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/template1.docx +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/template_for_multitable.docx +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/template_text.docx +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/template_without_text.docx +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/templates.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/xsl/convert.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/template/xsl/xmltohtml.xsl +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/chemparse.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/download.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/dsrmath.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/options.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/platon.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/pupdate.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/settings.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/shred.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/spgr_format.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif/tools/statusbar.py +0 -0
- {finalcif-144 → finalcif-147}/finalcif.exe +0 -0
- {finalcif-144 → finalcif-147}/install_requirements +0 -0
- {finalcif-144 → finalcif-147}/install_requirements.bat +0 -0
- {finalcif-144 → finalcif-147}/pyproject.toml +0 -0
- {finalcif-144 → finalcif-147}/requirements_devel.txt +0 -0
- {finalcif-144 → finalcif-147}/requirements_doku.txt +0 -0
- {finalcif-144 → finalcif-147}/run_finalcif +0 -0
- {finalcif-144 → finalcif-147}/run_finalcif.bat +0 -0
- {finalcif-144 → finalcif-147}/screenshots/finalcif_checkcif.png +0 -0
- {finalcif-144 → finalcif-147}/screenshots/finalcif_details.png +0 -0
- {finalcif-144 → finalcif-147}/screenshots/finalcif_loops.png +0 -0
- {finalcif-144 → finalcif-147}/screenshots/finalcif_loops2.png +0 -0
- {finalcif-144 → finalcif-147}/screenshots/finalcif_main.png +0 -0
- {finalcif-144 → finalcif-147}/screenshots/finalcif_report.png +0 -0
- {finalcif-144 → finalcif-147}/screenshots/finalcif_responses.png +0 -0
- {finalcif-144 → finalcif-147}/update.exe +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: finalcif
|
|
3
|
-
Version:
|
|
3
|
+
Version: 147
|
|
4
4
|
Summary: CIF file editor
|
|
5
5
|
Project-URL: Homepage, https://dkratzert.de/finalcif.html
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/dkratzert/FinalCif/issues
|
|
@@ -16,10 +16,10 @@ Requires-Dist: certifi
|
|
|
16
16
|
Requires-Dist: chardet
|
|
17
17
|
Requires-Dist: crossrefapi
|
|
18
18
|
Requires-Dist: docxtpl
|
|
19
|
-
Requires-Dist: gemmi
|
|
19
|
+
Requires-Dist: gemmi<0.7.0
|
|
20
20
|
Requires-Dist: html2text
|
|
21
21
|
Requires-Dist: lxml
|
|
22
|
-
Requires-Dist: numpy
|
|
22
|
+
Requires-Dist: numpy
|
|
23
23
|
Requires-Dist: pefile
|
|
24
24
|
Requires-Dist: pybind11
|
|
25
25
|
Requires-Dist: pyenchant
|
|
@@ -29,6 +29,7 @@ from finalcif.app_path import application_path
|
|
|
29
29
|
# QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
|
|
30
30
|
from finalcif.cif.checkcif.checkcif import MyHTMLParser, AlertHelp, CheckCif
|
|
31
31
|
from finalcif.cif.cif_file_io import CifContainer, GemmiError
|
|
32
|
+
from finalcif.cif import cif_order
|
|
32
33
|
from finalcif.cif.cod.deposit import CODdeposit
|
|
33
34
|
from finalcif.cif.text import utf8_to_str, quote
|
|
34
35
|
from finalcif.datafiles.bruker_data import BrukerData
|
|
@@ -61,6 +62,7 @@ from finalcif.tools.platon import PlatonRunner
|
|
|
61
62
|
from finalcif.tools.settings import FinalCifSettings
|
|
62
63
|
from finalcif.tools.shred import ShredCIF
|
|
63
64
|
from finalcif.tools.space_groups import SpaceGroups
|
|
65
|
+
from finalcif.tools.spgr_format import spgrps
|
|
64
66
|
from finalcif.tools.statusbar import StatusBar
|
|
65
67
|
from finalcif.tools.sumformula import formula_str_to_dict, sum_formula_to_html
|
|
66
68
|
|
|
@@ -104,6 +106,8 @@ class AppWindow(QMainWindow):
|
|
|
104
106
|
self.status_bar = StatusBar(ui=self.ui)
|
|
105
107
|
self.status_bar.show_message('FinalCif version {}'.format(VERSION))
|
|
106
108
|
self.authors: Union[AuthorLoops, None] = None
|
|
109
|
+
self.ui.cifOrderWidget.settings = self.settings
|
|
110
|
+
self.ui.cifOrderWidget.set_order_from_settings(self.settings)
|
|
107
111
|
self.set_window_size_and_position()
|
|
108
112
|
self.ui.cif_main_table.installEventFilter(self)
|
|
109
113
|
# Sorting desynchronized header and columns:
|
|
@@ -297,6 +301,14 @@ class AppWindow(QMainWindow):
|
|
|
297
301
|
self.ui.AddThisAuthorToLoopPushButton.setIcon(qta.icon('mdi.file-table-outline'))
|
|
298
302
|
with suppress(Exception):
|
|
299
303
|
self.ui.DeleteLoopAuthorTemplateButton.setIcon(qta.icon('mdi.delete-forever-outline'))
|
|
304
|
+
with suppress(Exception):
|
|
305
|
+
self.ui.cifOrderWidget.ui.deleteKeyPushButton.setIcon(qta.icon('mdi.delete-forever-outline'))
|
|
306
|
+
with suppress(Exception):
|
|
307
|
+
self.ui.cifOrderWidget.ui.moveUpPushButton.setIcon(qta.icon('mdi.chevron-up'))
|
|
308
|
+
self.ui.cifOrderWidget.ui.moveDownPushButton.setIcon(qta.icon('mdi.chevron-down'))
|
|
309
|
+
self.ui.cifOrderWidget.ui.saveSettingPushButton.setIcon(qta.icon('mdi.content-save'))
|
|
310
|
+
self.ui.cifOrderWidget.ui.addKeyPushButton.setIcon(qta.icon('mdi.plus'))
|
|
311
|
+
|
|
300
312
|
|
|
301
313
|
def connect_signals_and_slots(self) -> None:
|
|
302
314
|
"""
|
|
@@ -1113,7 +1125,7 @@ class AppWindow(QMainWindow):
|
|
|
1113
1125
|
"""
|
|
1114
1126
|
Generates a report document.
|
|
1115
1127
|
"""
|
|
1116
|
-
from finalcif.report.tables import
|
|
1128
|
+
from finalcif.report.tables import make_multi_tables
|
|
1117
1129
|
from finalcif.report.templated_report import TemplatedReport
|
|
1118
1130
|
current_block = self.ui.datanameComboBox.currentIndex()
|
|
1119
1131
|
if self.cif.doc[current_block].name == 'global':
|
|
@@ -1189,6 +1201,10 @@ class AppWindow(QMainWindow):
|
|
|
1189
1201
|
with suppress(Exception):
|
|
1190
1202
|
multitable = self.cif.finalcif_file_prefixed(prefix='', suffix='-multitable.docx')
|
|
1191
1203
|
arc.zip.write(filename=multitable, arcname=multitable.name)
|
|
1204
|
+
with suppress(Exception):
|
|
1205
|
+
prp_list = self.cif.finalcif_file.parent.glob('*.prp')
|
|
1206
|
+
sorted_prp = sorted(prp_list, key=lambda x: x.stat().st_mtime)
|
|
1207
|
+
arc.zip.write(filename=sorted_prp[-1], arcname=sorted_prp[-1].name)
|
|
1192
1208
|
|
|
1193
1209
|
def open_report_document(self, report_filename: Path, multi_table_document: Path) -> None:
|
|
1194
1210
|
if self.cif.is_multi_cif:
|
|
@@ -1238,10 +1254,12 @@ class AppWindow(QMainWindow):
|
|
|
1238
1254
|
self.cif.rename_data_name(''.join(self.ui.datanameComboBox.currentText().split(' ')))
|
|
1239
1255
|
self.store_data_from_table_rows()
|
|
1240
1256
|
self.save_ccdc_number()
|
|
1257
|
+
self.cif.set_order_keys(self.ui.cifOrderWidget.order_keys)
|
|
1241
1258
|
try:
|
|
1242
1259
|
self.cif.save()
|
|
1243
1260
|
self.status_bar.show_message(f' File Saved: {self.cif.finalcif_file}', 10)
|
|
1244
|
-
|
|
1261
|
+
if DEBUG:
|
|
1262
|
+
print('File saved ...')
|
|
1245
1263
|
return True
|
|
1246
1264
|
except Exception as e:
|
|
1247
1265
|
print('Unable to save file:')
|
|
@@ -1473,6 +1491,7 @@ class AppWindow(QMainWindow):
|
|
|
1473
1491
|
self.ui.datanameComboBox.blockSignals(False)
|
|
1474
1492
|
if self.cif.is_multi_cif:
|
|
1475
1493
|
self._flash_block_combobox()
|
|
1494
|
+
self.cif.set_order_keys(self.ui.cifOrderWidget.order_keys)
|
|
1476
1495
|
# Enable to find widgets without parent:
|
|
1477
1496
|
# QtCore.QTimer(self).singleShot(1000, self.find_widgets_without_parent)
|
|
1478
1497
|
|
|
@@ -1604,8 +1623,9 @@ class AppWindow(QMainWindow):
|
|
|
1604
1623
|
|
|
1605
1624
|
def fill_space_group_lineedit(self) -> None:
|
|
1606
1625
|
try:
|
|
1607
|
-
self.
|
|
1608
|
-
|
|
1626
|
+
txt = (f'<body style="">{SpaceGroups().to_html(self.cif.space_group)} '
|
|
1627
|
+
f' ({spgrps[self.cif.space_group][1].get("itnumber")})</body>')
|
|
1628
|
+
self.ui.Spacegroup_top_LineEdit.setText(txt)
|
|
1609
1629
|
except Exception as e:
|
|
1610
1630
|
print('Space group error:', str(e))
|
|
1611
1631
|
self.ui.Spacegroup_top_LineEdit.setText(self.cif.space_group)
|
|
@@ -1910,6 +1930,7 @@ class AppWindow(QMainWindow):
|
|
|
1910
1930
|
"""
|
|
1911
1931
|
Adds the cif content to the main table. also add reference to FinalCif.
|
|
1912
1932
|
"""
|
|
1933
|
+
self.cif.set_essential_keys(self.ui.cifOrderWidget.essential_keys)
|
|
1913
1934
|
for key, value in self.cif.key_value_pairs():
|
|
1914
1935
|
if not value or value == '?' or value == "'?'":
|
|
1915
1936
|
self.missing_data.add(key)
|
|
@@ -16,11 +16,11 @@ from gemmi.cif import as_string, Document, Loop
|
|
|
16
16
|
from packaging.version import Version
|
|
17
17
|
from shelxfile import Shelxfile
|
|
18
18
|
|
|
19
|
-
from finalcif.cif.cif_order import order, special_keys
|
|
19
|
+
from finalcif.cif.cif_order import order, special_keys, essential_keys, non_centrosymm_keys
|
|
20
20
|
from finalcif.cif.hkl import HKL, Limit
|
|
21
21
|
from finalcif.cif.text import utf8_to_str, quote, retranslate_delimiter
|
|
22
22
|
from finalcif.datafiles.utils import DSRFind
|
|
23
|
-
from finalcif.tools.misc import
|
|
23
|
+
from finalcif.tools.misc import isnumeric, grouper, strip_finalcif_of_name, \
|
|
24
24
|
_angstrom_to_x
|
|
25
25
|
|
|
26
26
|
|
|
@@ -42,7 +42,6 @@ class CifContainer():
|
|
|
42
42
|
the existing document is opened.
|
|
43
43
|
"""
|
|
44
44
|
self.picometer: bool = False
|
|
45
|
-
self._hkl_file: str = ''
|
|
46
45
|
self._abs_hkl_details: Dict[str, str] = {}
|
|
47
46
|
if isinstance(file, str):
|
|
48
47
|
self.fileobj = Path(file)
|
|
@@ -67,6 +66,16 @@ class CifContainer():
|
|
|
67
66
|
self.shx = Shelxfile(verbose=True)
|
|
68
67
|
self.shx.read_string(self.res_file_data[1:-1])
|
|
69
68
|
self._on_load()
|
|
69
|
+
self.order = []
|
|
70
|
+
self.essential_keys = []
|
|
71
|
+
self.set_order_keys(order)
|
|
72
|
+
self.set_essential_keys(essential_keys)
|
|
73
|
+
|
|
74
|
+
def set_order_keys(self, keys: List[str]) -> None:
|
|
75
|
+
self.order = keys
|
|
76
|
+
|
|
77
|
+
def set_essential_keys(self, keys: List[str]) -> None:
|
|
78
|
+
self.essential_keys = keys
|
|
70
79
|
|
|
71
80
|
@property
|
|
72
81
|
def path_base(self) -> Path:
|
|
@@ -139,7 +148,6 @@ class CifContainer():
|
|
|
139
148
|
self.doc.check_for_duplicates()
|
|
140
149
|
except RuntimeError as e:
|
|
141
150
|
raise GemmiError(e)
|
|
142
|
-
self.order = order
|
|
143
151
|
self.dsr_used = DSRFind(self.res_file_data).dsr_used
|
|
144
152
|
self.atomic_struct: gemmi.SmallStructure = gemmi.make_small_structure_from_block(self.block)
|
|
145
153
|
# A dictionary to convert Atom names like 'C1_2' or 'Ga3' into Element names like 'C' or 'Ga'
|
|
@@ -272,6 +280,8 @@ class CifContainer():
|
|
|
272
280
|
if self.is_empty():
|
|
273
281
|
print(f'File {filename} is empty.')
|
|
274
282
|
return
|
|
283
|
+
if not self.is_writable(filename):
|
|
284
|
+
raise PermissionError(f'Failed to open {filename.resolve()} for writing: Operation not permitted')
|
|
275
285
|
self.order_cif_keys()
|
|
276
286
|
print('Saving CIF to', Path(filename).resolve())
|
|
277
287
|
if Version(gemmi.__version__) > Version('0.6.3'):
|
|
@@ -285,6 +295,18 @@ class CifContainer():
|
|
|
285
295
|
else:
|
|
286
296
|
self.doc.write_file(str(filename), gemmi.cif.Style.Indent35)
|
|
287
297
|
|
|
298
|
+
def is_writable(self, filepath: Union[Path, str]) -> bool:
|
|
299
|
+
filepath = Path(filepath)
|
|
300
|
+
try:
|
|
301
|
+
exist = filepath.exists()
|
|
302
|
+
with open(filepath, 'wb+') as f:
|
|
303
|
+
f.write(b'')
|
|
304
|
+
if not exist:
|
|
305
|
+
Path(filepath).unlink(missing_ok=True)
|
|
306
|
+
return True
|
|
307
|
+
except Exception:
|
|
308
|
+
return False
|
|
309
|
+
|
|
288
310
|
def order_cif_keys(self) -> None:
|
|
289
311
|
"""
|
|
290
312
|
Brings the current CIF in the specific order of the order list.
|
|
@@ -324,14 +346,10 @@ class CifContainer():
|
|
|
324
346
|
def hkl_file(self) -> str:
|
|
325
347
|
hkl_loop: Loop = self.get_loop('_diffrn_refln_index_h')
|
|
326
348
|
if hkl_loop and hkl_loop.width() > 4:
|
|
327
|
-
|
|
328
|
-
self._hkl_file = self._hkl_from_cif_format(hkl_loop)
|
|
329
|
-
return self._hkl_file
|
|
349
|
+
return self._hkl_from_cif_format(hkl_loop)
|
|
330
350
|
else:
|
|
331
351
|
# returns an empty string if no cif hkl was found:
|
|
332
|
-
|
|
333
|
-
self._hkl_file = self._hkl_from_shelx()
|
|
334
|
-
return self._hkl_file
|
|
352
|
+
return self._hkl_from_shelx()
|
|
335
353
|
|
|
336
354
|
def _hkl_from_cif_format(self, hkl_loop: Loop) -> str:
|
|
337
355
|
hkl_list = []
|
|
@@ -377,7 +395,7 @@ class CifContainer():
|
|
|
377
395
|
return HKL(self.hkl_file, self.block.name, hklf_type=self.hklf_number).get_hkl_min_max()
|
|
378
396
|
|
|
379
397
|
def _hklf_number_from_shelxl_file(self) -> int:
|
|
380
|
-
if self.shx.hklf:
|
|
398
|
+
if self.shx and self.shx.hklf:
|
|
381
399
|
return self.shx.hklf.n if self.shx.hklf.n != 0 else 4
|
|
382
400
|
else:
|
|
383
401
|
return 4
|
|
@@ -501,8 +519,11 @@ class CifContainer():
|
|
|
501
519
|
|
|
502
520
|
def add_loop_from_columns(self, loop_tags: List[str],
|
|
503
521
|
column_values: Union[List[List[str]], Tuple[Tuple[str]]]) -> gemmi.cif.Loop:
|
|
504
|
-
|
|
505
|
-
|
|
522
|
+
try:
|
|
523
|
+
gemmi_loop = self.init_loop(loop_tags)
|
|
524
|
+
gemmi_loop.set_all_values(column_values)
|
|
525
|
+
except RuntimeError as err:
|
|
526
|
+
raise Exception('Gemmi raised an exception') from err
|
|
506
527
|
return gemmi_loop
|
|
507
528
|
|
|
508
529
|
@property
|
|
@@ -829,7 +850,7 @@ class CifContainer():
|
|
|
829
850
|
publ_loop = self.block.find_loop('_geom_angle_publ_flag')
|
|
830
851
|
angle = namedtuple('angle', ('label1', 'label2', 'label3', 'angle_val', 'symm1', 'symm2'))
|
|
831
852
|
for label1, label2, label3, angle_val, symm1, symm2, publ in \
|
|
832
|
-
|
|
853
|
+
zip(label1, label2, label3, angle_val, symm1, symm2, publ_loop):
|
|
833
854
|
if (without_H and (self.ishydrogen(label1) or self.ishydrogen(label2) or
|
|
834
855
|
self.ishydrogen(label3)) or (self.yes_not_set(publ))):
|
|
835
856
|
continue
|
|
@@ -901,7 +922,7 @@ class CifContainer():
|
|
|
901
922
|
hydr = namedtuple('HydrogenBond', ('label_d', 'label_h', 'label_a', 'dist_dh', 'dist_ha', 'dist_da',
|
|
902
923
|
'angle_dha', 'symm'))
|
|
903
924
|
for label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ in (
|
|
904
|
-
|
|
925
|
+
zip(label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ_loop)):
|
|
905
926
|
if self.yes_not_set(publ):
|
|
906
927
|
continue
|
|
907
928
|
if self.picometer:
|
|
@@ -957,7 +978,7 @@ class CifContainer():
|
|
|
957
978
|
"""
|
|
958
979
|
Check if there are keys not in the cif but in essential_keys and append them if so.
|
|
959
980
|
"""
|
|
960
|
-
for key in essential_keys:
|
|
981
|
+
for key in self.essential_keys:
|
|
961
982
|
if key not in all_keys:
|
|
962
983
|
if self._is_centrokey(key):
|
|
963
984
|
continue
|
|
@@ -212,6 +212,8 @@ order = [
|
|
|
212
212
|
'_diffrn_radiation_monochromator',
|
|
213
213
|
'_diffrn_radiation_polarisn_norm',
|
|
214
214
|
'_diffrn_radiation_collimation',
|
|
215
|
+
'_bruker_diffrn_measurement_temperature_device',
|
|
216
|
+
'_bruker_diffrn_measurement_temperature_device_make',
|
|
215
217
|
'_olex2_diffrn_ambient_temperature_device',
|
|
216
218
|
'_diffrn_measurement_ambient_temperature_device_make',
|
|
217
219
|
'_diffrn_radiation_probe',
|
|
@@ -361,3 +363,129 @@ order = [
|
|
|
361
363
|
'_bruker_diffrn_runs_theta',
|
|
362
364
|
'_bruker_diffrn_runs_distance',
|
|
363
365
|
]
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# These keywords will end up in the CIF in any case:
|
|
369
|
+
essential_keys = (
|
|
370
|
+
# '_atom_sites_solution_secondary'
|
|
371
|
+
# '_diffrn_measurement_specimen_adhesive'
|
|
372
|
+
# '_diffrn_source_power'
|
|
373
|
+
# '_diffrn_source_target'
|
|
374
|
+
# '_olex2_diffrn_ambient_temperature_device'
|
|
375
|
+
'_diffrn_measurement_ambient_temperature_device_make',
|
|
376
|
+
'_atom_sites_solution_hydrogens',
|
|
377
|
+
'_atom_sites_solution_primary',
|
|
378
|
+
# '_audit_contact_author_name',
|
|
379
|
+
# '_audit_contact_author_address',
|
|
380
|
+
# '_audit_contact_author_email',
|
|
381
|
+
# '_audit_contact_author_phone',
|
|
382
|
+
'_audit_creation_method',
|
|
383
|
+
'_publ_section_references',
|
|
384
|
+
'_cell_angle_alpha',
|
|
385
|
+
'_cell_angle_beta',
|
|
386
|
+
'_cell_angle_gamma',
|
|
387
|
+
'_cell_formula_units_Z',
|
|
388
|
+
'_cell_length_a',
|
|
389
|
+
'_cell_length_b',
|
|
390
|
+
'_cell_length_c',
|
|
391
|
+
'_cell_measurement_reflns_used',
|
|
392
|
+
'_cell_measurement_temperature',
|
|
393
|
+
'_cell_measurement_theta_max',
|
|
394
|
+
'_cell_measurement_theta_min',
|
|
395
|
+
'_cell_volume',
|
|
396
|
+
'_chemical_absolute_configuration',
|
|
397
|
+
'_chemical_formula_moiety',
|
|
398
|
+
'_chemical_formula_sum',
|
|
399
|
+
'_chemical_formula_weight',
|
|
400
|
+
'_chemical_melting_point',
|
|
401
|
+
'_chemical_name_common',
|
|
402
|
+
'_chemical_name_systematic',
|
|
403
|
+
'_computing_cell_refinement',
|
|
404
|
+
'_computing_data_collection',
|
|
405
|
+
'_computing_data_reduction',
|
|
406
|
+
'_computing_molecular_graphics',
|
|
407
|
+
# '_computing_publication_material',
|
|
408
|
+
'_computing_structure_refinement',
|
|
409
|
+
'_computing_structure_solution',
|
|
410
|
+
# '_diffrn_ambient_environment',
|
|
411
|
+
'_diffrn_ambient_temperature',
|
|
412
|
+
'_diffrn_detector',
|
|
413
|
+
'_diffrn_detector_area_resol_mean',
|
|
414
|
+
'_diffrn_detector_type',
|
|
415
|
+
'_diffrn_measured_fraction_theta_full',
|
|
416
|
+
'_diffrn_measured_fraction_theta_max',
|
|
417
|
+
'_diffrn_measurement_device',
|
|
418
|
+
'_diffrn_measurement_device_type',
|
|
419
|
+
'_diffrn_measurement_method',
|
|
420
|
+
'_diffrn_measurement_specimen_support',
|
|
421
|
+
'_diffrn_radiation_monochromator',
|
|
422
|
+
'_diffrn_radiation_probe',
|
|
423
|
+
'_diffrn_radiation_type',
|
|
424
|
+
'_diffrn_radiation_wavelength',
|
|
425
|
+
'_diffrn_reflns_Laue_measured_fraction_full',
|
|
426
|
+
'_diffrn_reflns_Laue_measured_fraction_max',
|
|
427
|
+
'_diffrn_reflns_av_R_equivalents',
|
|
428
|
+
'_diffrn_reflns_av_unetI/netI',
|
|
429
|
+
'_diffrn_reflns_number',
|
|
430
|
+
'_diffrn_reflns_point_group_measured_fraction_full',
|
|
431
|
+
'_diffrn_reflns_point_group_measured_fraction_max',
|
|
432
|
+
'_diffrn_reflns_theta_full',
|
|
433
|
+
'_diffrn_reflns_theta_max',
|
|
434
|
+
'_diffrn_reflns_theta_min',
|
|
435
|
+
'_diffrn_source',
|
|
436
|
+
'_diffrn_source_current',
|
|
437
|
+
'_diffrn_source_type',
|
|
438
|
+
'_diffrn_source_voltage',
|
|
439
|
+
'_exptl_absorpt_coefficient_mu',
|
|
440
|
+
'_exptl_absorpt_correction_T_max',
|
|
441
|
+
'_exptl_absorpt_correction_T_min',
|
|
442
|
+
'_exptl_absorpt_correction_type',
|
|
443
|
+
'_exptl_absorpt_process_details',
|
|
444
|
+
'_exptl_crystal_F_000',
|
|
445
|
+
'_exptl_crystal_colour',
|
|
446
|
+
'_exptl_crystal_density_diffrn',
|
|
447
|
+
'_exptl_crystal_density_meas',
|
|
448
|
+
'_exptl_crystal_density_method',
|
|
449
|
+
'_exptl_crystal_description',
|
|
450
|
+
'_exptl_crystal_recrystallization_method',
|
|
451
|
+
'_exptl_crystal_size_max',
|
|
452
|
+
'_exptl_crystal_size_mid',
|
|
453
|
+
'_exptl_crystal_size_min',
|
|
454
|
+
'_exptl_special_details',
|
|
455
|
+
'_geom_special_details',
|
|
456
|
+
'_refine_ls_R_factor_all',
|
|
457
|
+
'_refine_ls_R_factor_gt',
|
|
458
|
+
'_refine_ls_abs_structure_Flack',
|
|
459
|
+
'_refine_ls_abs_structure_details',
|
|
460
|
+
'_refine_ls_extinction_coef',
|
|
461
|
+
'_refine_ls_extinction_method',
|
|
462
|
+
'_refine_ls_goodness_of_fit_ref',
|
|
463
|
+
'_refine_ls_hydrogen_treatment',
|
|
464
|
+
'_refine_ls_matrix_type',
|
|
465
|
+
'_refine_ls_number_parameters',
|
|
466
|
+
'_refine_ls_number_reflns',
|
|
467
|
+
'_refine_ls_number_restraints',
|
|
468
|
+
'_refine_ls_restrained_S_all',
|
|
469
|
+
'_refine_ls_shift/su_max',
|
|
470
|
+
'_refine_ls_shift/su_mean',
|
|
471
|
+
'_refine_ls_structure_factor_coef',
|
|
472
|
+
'_refine_ls_wR_factor_gt',
|
|
473
|
+
'_refine_ls_wR_factor_ref',
|
|
474
|
+
'_refine_ls_weighting_details',
|
|
475
|
+
'_refine_ls_weighting_scheme',
|
|
476
|
+
'_refine_special_details',
|
|
477
|
+
'_reflns_Friedel_coverage',
|
|
478
|
+
'_reflns_Friedel_fraction_full',
|
|
479
|
+
'_reflns_Friedel_fraction_max',
|
|
480
|
+
'_reflns_number_gt',
|
|
481
|
+
'_reflns_number_total',
|
|
482
|
+
'_reflns_special_details',
|
|
483
|
+
'_reflns_threshold_expression',
|
|
484
|
+
'_space_group_IT_number',
|
|
485
|
+
'_space_group_crystal_system',
|
|
486
|
+
'_space_group_name_H-M_alt',
|
|
487
|
+
'_space_group_name_Hall',
|
|
488
|
+
# '_space_group_symop_operation_xyz'
|
|
489
|
+
)
|
|
490
|
+
non_centrosymm_keys = ('_chemical_absolute_configuration', '_refine_ls_abs_structure_Flack',
|
|
491
|
+
'_refine_ls_abs_structure_details')
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import enum
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import List, TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
import gemmi
|
|
9
|
+
from PyQt5 import QtWidgets, QtCore
|
|
10
|
+
|
|
11
|
+
from finalcif.cif import cif_order
|
|
12
|
+
from finalcif.ciforder.order_ui import Ui_CifOrderForm
|
|
13
|
+
from finalcif.gui import dialogs
|
|
14
|
+
from finalcif.gui.custom_classes import CifOrderItem
|
|
15
|
+
from finalcif.gui.dialogs import cif_file_save_dialog, show_general_warning
|
|
16
|
+
from finalcif.gui.new_key_dialog import NewKey
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from finalcif.tools.settings import FinalCifSettings
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Column(enum.IntEnum):
|
|
23
|
+
key = 0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class CifOrder(QtWidgets.QGroupBox):
|
|
27
|
+
def __init__(self, parent=None, cif_file: Path = None):
|
|
28
|
+
super().__init__(parent)
|
|
29
|
+
self.ui = Ui_CifOrderForm()
|
|
30
|
+
self.ui.setupUi(self)
|
|
31
|
+
self.cif = None
|
|
32
|
+
self.settings = None
|
|
33
|
+
self.essential_keys = cif_order.essential_keys
|
|
34
|
+
self.set_keys(cif_order.order)
|
|
35
|
+
if cif_file is not None:
|
|
36
|
+
self.set_keys_from_cif(cif_file)
|
|
37
|
+
self.connect_signals_and_slots()
|
|
38
|
+
|
|
39
|
+
def set_order_from_settings(self, settings: FinalCifSettings = None):
|
|
40
|
+
self.settings = settings
|
|
41
|
+
if settings is not None:
|
|
42
|
+
order = settings.load_settings_list('cif_order', 'order')
|
|
43
|
+
essentials = settings.load_settings_list('cif_order', 'essentials')
|
|
44
|
+
if order:
|
|
45
|
+
self.essential_keys = essentials
|
|
46
|
+
self.set_keys(order)
|
|
47
|
+
|
|
48
|
+
def connect_signals_and_slots(self):
|
|
49
|
+
self.ui.importCifPushButton.clicked.connect(self.import_cif)
|
|
50
|
+
self.ui.restoreDefaultPushButton.clicked.connect(self.restore_default)
|
|
51
|
+
self.ui.addKeyPushButton.clicked.connect(self.open_add_cif_key)
|
|
52
|
+
self.ui.saveSettingPushButton.clicked.connect(self.save_setting)
|
|
53
|
+
self.ui.deleteKeyPushButton.clicked.connect(self.delete_keys)
|
|
54
|
+
self.ui.exportToCifPushButton.clicked.connect(self.export_cif)
|
|
55
|
+
# Connect signals for moveUpPushButton
|
|
56
|
+
self.ui.moveUpPushButton.pressed.connect(lambda: self.start_repeated_action(self.move_row_up))
|
|
57
|
+
self.ui.moveUpPushButton.released.connect(self.stop_repeated_action)
|
|
58
|
+
# Connect signals for moveDownPushButton
|
|
59
|
+
self.ui.moveDownPushButton.pressed.connect(lambda: self.start_repeated_action(self.move_row_down))
|
|
60
|
+
self.ui.moveDownPushButton.released.connect(self.stop_repeated_action)
|
|
61
|
+
# Timer for repeated actions
|
|
62
|
+
self.timer = QtCore.QTimer(self)
|
|
63
|
+
self.timer.setInterval(170)
|
|
64
|
+
self.timer.timeout.connect(self.perform_repeated_action)
|
|
65
|
+
self.current_action = None
|
|
66
|
+
|
|
67
|
+
def start_repeated_action(self, action):
|
|
68
|
+
"""Start the timer with the given action."""
|
|
69
|
+
self.current_action = action
|
|
70
|
+
action() # Perform the action immediately
|
|
71
|
+
self.timer.start()
|
|
72
|
+
|
|
73
|
+
def stop_repeated_action(self):
|
|
74
|
+
"""Stop the timer and reset the current action."""
|
|
75
|
+
self.timer.stop()
|
|
76
|
+
self.current_action = None
|
|
77
|
+
|
|
78
|
+
def perform_repeated_action(self):
|
|
79
|
+
"""Perform the currently set action."""
|
|
80
|
+
if self.current_action:
|
|
81
|
+
self.current_action()
|
|
82
|
+
|
|
83
|
+
def move_row_up(self):
|
|
84
|
+
current_row = self.ui.cifOrderTableWidget.currentRow()
|
|
85
|
+
if current_row > 0:
|
|
86
|
+
self.swap_rows(current_row, current_row - 1)
|
|
87
|
+
self.ui.cifOrderTableWidget.setCurrentCell(current_row - 1, Column.key)
|
|
88
|
+
|
|
89
|
+
def move_row_down(self):
|
|
90
|
+
table = self.ui.cifOrderTableWidget
|
|
91
|
+
current_row = table.currentRow()
|
|
92
|
+
if current_row < table.rowCount() - 1:
|
|
93
|
+
self.swap_rows(current_row, current_row + 1)
|
|
94
|
+
table.setCurrentCell(current_row + 1, Column.key)
|
|
95
|
+
|
|
96
|
+
def swap_rows(self, row1, row2):
|
|
97
|
+
table = self.ui.cifOrderTableWidget
|
|
98
|
+
item1 = table.item(row1, Column.key)
|
|
99
|
+
item2 = table.item(row2, Column.key)
|
|
100
|
+
if item1 and item2:
|
|
101
|
+
text1 = item1.text()
|
|
102
|
+
text2 = item2.text()
|
|
103
|
+
check_state1 = item1.checkState()
|
|
104
|
+
check_state2 = item2.checkState()
|
|
105
|
+
item1.setText(text2)
|
|
106
|
+
item1.setCheckState(check_state2)
|
|
107
|
+
item2.setText(text1)
|
|
108
|
+
item2.setCheckState(check_state1)
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def order_keys(self):
|
|
112
|
+
keys = []
|
|
113
|
+
for row in range(self.ui.cifOrderTableWidget.rowCount()):
|
|
114
|
+
key = self.ui.cifOrderTableWidget.item(row, Column.key).text()
|
|
115
|
+
keys.append(key)
|
|
116
|
+
return keys
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def order_essentials(self):
|
|
120
|
+
essentials = []
|
|
121
|
+
for row in range(self.ui.cifOrderTableWidget.rowCount()):
|
|
122
|
+
item = self.ui.cifOrderTableWidget.item(row, Column.key)
|
|
123
|
+
essential = item.checkState()
|
|
124
|
+
if essential:
|
|
125
|
+
essentials.append(item.text())
|
|
126
|
+
return essentials
|
|
127
|
+
|
|
128
|
+
def set_keys_from_cif(self, cif_file) -> None:
|
|
129
|
+
try:
|
|
130
|
+
self.cif = gemmi.cif.read_file(cif_file)
|
|
131
|
+
block = self.cif.sole_block()
|
|
132
|
+
except Exception:
|
|
133
|
+
show_general_warning(self, 'Unable to load file')
|
|
134
|
+
return
|
|
135
|
+
keys = [x.pair[0] for x in block if x.pair is not None]
|
|
136
|
+
essentials = [x.pair[0] for x in block if x.pair is not None and x.pair[1] == 'True']
|
|
137
|
+
self.set_essentials(essentials)
|
|
138
|
+
self.set_keys(keys)
|
|
139
|
+
|
|
140
|
+
def set_essentials(self, essentials):
|
|
141
|
+
self.essential_keys = essentials
|
|
142
|
+
|
|
143
|
+
def set_keys(self, order_keys: List[str] = None):
|
|
144
|
+
self.ui.cifOrderTableWidget.setRowCount(0)
|
|
145
|
+
row = 0
|
|
146
|
+
for key_text in order_keys:
|
|
147
|
+
if not key_text:
|
|
148
|
+
continue
|
|
149
|
+
self.ui.cifOrderTableWidget.insertRow(row)
|
|
150
|
+
self.set_row_text(key_text, row)
|
|
151
|
+
row += 1
|
|
152
|
+
# self.ui.cifOrderTableWidget.resizeColumnsToContents()
|
|
153
|
+
|
|
154
|
+
def set_row_text(self, key_text: str, row: int) -> None:
|
|
155
|
+
item1 = CifOrderItem(key_text)
|
|
156
|
+
item1.setFlags(item1.flags() | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
|
|
157
|
+
item1.setText(key_text)
|
|
158
|
+
if key_text in self.essential_keys:
|
|
159
|
+
item1.setEssential(True)
|
|
160
|
+
else:
|
|
161
|
+
item1.setEssential(False)
|
|
162
|
+
self.ui.cifOrderTableWidget.setItem(row, Column.key, item1)
|
|
163
|
+
|
|
164
|
+
def set_keys_from_settings(self, keys: List[str]):
|
|
165
|
+
self.set_keys(keys)
|
|
166
|
+
|
|
167
|
+
def import_cif(self):
|
|
168
|
+
cif_file = dialogs.cif_file_open_dialog()
|
|
169
|
+
if self._file_is_there(cif_file):
|
|
170
|
+
self.set_keys_from_cif(cif_file)
|
|
171
|
+
|
|
172
|
+
def _file_is_there(self, cif_file: str) -> bool:
|
|
173
|
+
return cif_file is not None and Path(cif_file).is_file() and Path(cif_file).exists()
|
|
174
|
+
|
|
175
|
+
def restore_default(self):
|
|
176
|
+
self.essential_keys = cif_order.essential_keys
|
|
177
|
+
self.settings.save_settings_list('cif_order', 'order', [])
|
|
178
|
+
self.settings.save_settings_list('cif_order', 'essentials', [])
|
|
179
|
+
self.set_keys(cif_order.order)
|
|
180
|
+
|
|
181
|
+
def open_add_cif_key(self):
|
|
182
|
+
new_key = NewKey(self)
|
|
183
|
+
new_key.show()
|
|
184
|
+
new_key.new_key_added.connect(self.add_key)
|
|
185
|
+
|
|
186
|
+
def add_key(self, key: str) -> None:
|
|
187
|
+
if key not in self.order_keys:
|
|
188
|
+
self.ui.cifOrderTableWidget.insertRow(0)
|
|
189
|
+
self.set_row_text(key, 0)
|
|
190
|
+
|
|
191
|
+
def save_setting(self):
|
|
192
|
+
self.settings.save_settings_list('cif_order', 'order', self.order_keys)
|
|
193
|
+
self.settings.save_settings_list('cif_order', 'essentials', self.order_essentials)
|
|
194
|
+
self.essential_keys = self.order_essentials
|
|
195
|
+
|
|
196
|
+
def delete_keys(self):
|
|
197
|
+
items = self.ui.cifOrderTableWidget.selectedItems()
|
|
198
|
+
for item in items:
|
|
199
|
+
self.ui.cifOrderTableWidget.removeRow(item.row())
|
|
200
|
+
|
|
201
|
+
def export_cif(self):
|
|
202
|
+
doc = gemmi.cif.Document()
|
|
203
|
+
blockname = 'FinalCif_keys_order'
|
|
204
|
+
block = doc.add_new_block(blockname)
|
|
205
|
+
for key in self.order_keys:
|
|
206
|
+
value = 'True' if key in self.order_essentials else 'False'
|
|
207
|
+
block.set_pair(key, value)
|
|
208
|
+
filename = cif_file_save_dialog(blockname.lower() + '.cif')
|
|
209
|
+
if not filename.strip():
|
|
210
|
+
return
|
|
211
|
+
try:
|
|
212
|
+
doc.write_file(filename, style=gemmi.cif.Style.Indent35)
|
|
213
|
+
except PermissionError:
|
|
214
|
+
if Path(filename).is_dir():
|
|
215
|
+
return
|
|
216
|
+
show_general_warning(self, 'No permission to write file to {}'.format(Path(filename).resolve()))
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if __name__ == "__main__":
|
|
220
|
+
from finalcif.tools.settings import FinalCifSettings
|
|
221
|
+
|
|
222
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
223
|
+
# form = CifOrder(parent=None, cif_file=Path('test-data/1000007.cif').resolve())
|
|
224
|
+
settings = FinalCifSettings()
|
|
225
|
+
form = CifOrder(parent=None)
|
|
226
|
+
form.set_order_from_settings(settings)
|
|
227
|
+
form.show()
|
|
228
|
+
form.raise_()
|
|
229
|
+
sys.exit(app.exec_())
|