finalcif 151__tar.gz → 153__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-151 → finalcif-153}/.gitignore +1 -0
- finalcif-153/.python-version +1 -0
- {finalcif-151 → finalcif-153}/Finalcif_installer_win.spec +1 -0
- {finalcif-151 → finalcif-153}/PKG-INFO +7 -4
- finalcif-153/finalcif/__init__.py +2 -0
- {finalcif-151 → finalcif-153}/finalcif/appwindow.py +30 -22
- {finalcif-151 → finalcif-153}/finalcif/cif/checkcif/checkcif.py +1 -1
- {finalcif-151 → finalcif-153}/finalcif/cif/cif_file_io.py +23 -15
- {finalcif-151 → finalcif-153}/finalcif/cif/cod/deposit.py +5 -5
- {finalcif-151 → finalcif-153}/finalcif/cif/hkl.py +5 -1
- {finalcif-151 → finalcif-153}/finalcif/ciforder/order.py +1 -1
- {finalcif-151 → finalcif-153}/finalcif/ciforder/order_ui.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/datafiles/shelx_lst.py +21 -12
- {finalcif-151 → finalcif-153}/finalcif/displaymol/molecule2D.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/displaymol/vtk_molecule.py +2 -2
- {finalcif-151 → finalcif-153}/finalcif/equip_property/author_loop_templates.py +30 -2
- {finalcif-151 → finalcif-153}/finalcif/equip_property/equipment.py +2 -2
- {finalcif-151 → finalcif-153}/finalcif/equip_property/properties.py +2 -2
- {finalcif-151 → finalcif-153}/finalcif/finalcif_start.py +4 -2
- {finalcif-151 → finalcif-153}/finalcif/gui/block_combobox.py +1 -1
- {finalcif-151 → finalcif-153}/finalcif/gui/combobox.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/gui/custom_classes.py +4 -4
- {finalcif-151 → finalcif-153}/finalcif/gui/dialogs.py +19 -15
- {finalcif-151 → finalcif-153}/finalcif/gui/edit_button.py +1 -1
- {finalcif-151 → finalcif-153}/finalcif/gui/equipmenttable.py +2 -2
- {finalcif-151 → finalcif-153}/finalcif/gui/file_editor.py +5 -5
- {finalcif-151 → finalcif-153}/finalcif/gui/finalcif_gui_ui.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/gui/import_selector_ui.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/gui/loop_creator.py +2 -2
- {finalcif-151 → finalcif-153}/finalcif/gui/loop_creator_ui.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/gui/loops.py +4 -4
- {finalcif-151 → finalcif-153}/finalcif/gui/mainstackwidget.py +1 -1
- {finalcif-151 → finalcif-153}/finalcif/gui/new_key_dialog.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/gui/new_key_dialog_ui.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/gui/plaintextedit.py +6 -6
- {finalcif-151 → finalcif-153}/finalcif/gui/playground.py +4 -4
- {finalcif-151 → finalcif-153}/finalcif/gui/propertytable.py +1 -1
- {finalcif-151 → finalcif-153}/finalcif/gui/spell_check_edit.py +4 -4
- {finalcif-151 → finalcif-153}/finalcif/gui/text_templates_ui.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/gui/text_value_editor.py +4 -4
- {finalcif-151 → finalcif-153}/finalcif/gui/vrf_classes.py +4 -4
- {finalcif-151 → finalcif-153}/finalcif/report/gui/mainwindow.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/report/templated_report.py +1 -1
- {finalcif-151 → finalcif-153}/finalcif/template/templates.py +7 -6
- {finalcif-151 → finalcif-153}/finalcif/tools/download.py +3 -3
- {finalcif-151 → finalcif-153}/finalcif/tools/platon.py +2 -2
- {finalcif-151 → finalcif-153}/finalcif/tools/settings.py +4 -3
- {finalcif-151 → finalcif-153}/pyproject.toml +7 -5
- {finalcif-151 → finalcif-153}/requirements.txt +2 -2
- finalcif-153/uv.lock +1273 -0
- finalcif-151/finalcif/__init__.py +0 -2
- finalcif-151/uv.lock +0 -1071
- {finalcif-151 → finalcif-153}/.gitattributes +0 -0
- {finalcif-151 → finalcif-153}/.ruff.toml +0 -0
- {finalcif-151 → finalcif-153}/.run/Make Documentation MAC.run.xml +0 -0
- {finalcif-151 → finalcif-153}/.run/compile_ui_files.run.xml +0 -0
- {finalcif-151 → finalcif-153}/.run/make documentation Windows.run.xml +0 -0
- {finalcif-151 → finalcif-153}/CODE_OF_CONDUCT.md +0 -0
- {finalcif-151 → finalcif-153}/CONTRIBUTING.md +0 -0
- {finalcif-151 → finalcif-153}/Finalcif_linux_onefile.spec +0 -0
- {finalcif-151 → finalcif-153}/Finalcif_mac.spec +0 -0
- {finalcif-151 → finalcif-153}/Hydrogen_solution_type.cif +0 -0
- {finalcif-151 → finalcif-153}/LICENSE +0 -0
- {finalcif-151 → finalcif-153}/README.md +0 -0
- {finalcif-151 → finalcif-153}/finalcif/app_path.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/all_cif_dicts.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/atoms.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/checkcif/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/cif_dict_foo.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/cif_order.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/cod/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/cod/deposit_check.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/cod/deposition_list.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/cod/doi.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/cod/upload.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/cod/website_parser.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/core_dict.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/modulation_dict.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/powder_dict.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/reference.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/restraints_dict.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/text.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/cif/twin_dict.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/ciforder/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/ciforder/order_ui.ui +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/bruker_data.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/bruker_frame.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/ccdc_mail.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/data.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/p4p_reader.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/sadabs.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/saint.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/datafiles/utils.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/displaymol/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/displaymol/sdm.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/equip_property/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/equip_property/tools.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/finalcif_gui_ui.ui +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/import_selector.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/import_selector_ui.ui +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/loop_creator_ui.ui +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/mixins.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/new_key_dialog_ui.ui +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/text_templates_ui.ui +0 -0
- {finalcif-151 → finalcif-153}/finalcif/gui/validators.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/icon/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/icon/finalcif.png +0 -0
- {finalcif-151 → finalcif-153}/finalcif/icon/finalcif2.ico +0 -0
- {finalcif-151 → finalcif-153}/finalcif/icon/finalcif2.png +0 -0
- {finalcif-151 → finalcif-153}/finalcif/icon/multitable.ico +0 -0
- {finalcif-151 → finalcif-153}/finalcif/icon/multitable.png +0 -0
- {finalcif-151 → finalcif-153}/finalcif/icon/multitable.xcf +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/archive_report.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/gui/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/gui/mainwindow.ui +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/mtools.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/references.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/report_text.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/symm.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/report/tables.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/bootstrap/bootstrap.min.css +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/machines/D8_VENTURE.cif +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/mathml2omml.xsl +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/report.tmpl +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/report_default.docx +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/template1.docx +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/template_for_multitable.docx +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/template_text.docx +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/template_without_text.docx +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/xsl/convert.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/template/xsl/xmltohtml.xsl +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/__init__.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/chemparse.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/dsrmath.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/misc.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/options.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/pupdate.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/shred.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/space_groups.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/spgr_format.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/statusbar.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif/tools/sumformula.py +0 -0
- {finalcif-151 → finalcif-153}/finalcif.exe +0 -0
- {finalcif-151 → finalcif-153}/install_requirements +0 -0
- {finalcif-151 → finalcif-153}/install_requirements.bat +0 -0
- {finalcif-151 → finalcif-153}/requirements_devel.txt +0 -0
- {finalcif-151 → finalcif-153}/requirements_doku.txt +0 -0
- {finalcif-151 → finalcif-153}/run_finalcif +0 -0
- {finalcif-151 → finalcif-153}/run_finalcif.bat +0 -0
- {finalcif-151 → finalcif-153}/screenshots/finalcif_checkcif.png +0 -0
- {finalcif-151 → finalcif-153}/screenshots/finalcif_details.png +0 -0
- {finalcif-151 → finalcif-153}/screenshots/finalcif_loops.png +0 -0
- {finalcif-151 → finalcif-153}/screenshots/finalcif_loops2.png +0 -0
- {finalcif-151 → finalcif-153}/screenshots/finalcif_main.png +0 -0
- {finalcif-151 → finalcif-153}/screenshots/finalcif_report.png +0 -0
- {finalcif-151 → finalcif-153}/screenshots/finalcif_responses.png +0 -0
- {finalcif-151 → finalcif-153}/update.exe +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cpython@3.12
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: finalcif
|
|
3
|
-
Version:
|
|
3
|
+
Version: 153
|
|
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
|
|
@@ -14,17 +14,20 @@ Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
|
14
14
|
Requires-Python: >=3.10
|
|
15
15
|
Requires-Dist: certifi
|
|
16
16
|
Requires-Dist: chardet
|
|
17
|
+
Requires-Dist: charset-normalizer
|
|
17
18
|
Requires-Dist: crossrefapi
|
|
18
19
|
Requires-Dist: docxtpl
|
|
19
|
-
Requires-Dist: gemmi
|
|
20
|
-
Requires-Dist: hatchling
|
|
20
|
+
Requires-Dist: gemmi
|
|
21
|
+
Requires-Dist: hatchling
|
|
21
22
|
Requires-Dist: html2text
|
|
22
23
|
Requires-Dist: lxml
|
|
23
24
|
Requires-Dist: numpy
|
|
25
|
+
Requires-Dist: packaging
|
|
24
26
|
Requires-Dist: pefile
|
|
25
27
|
Requires-Dist: pybind11
|
|
26
28
|
Requires-Dist: pyenchant
|
|
27
|
-
Requires-Dist: pyside6
|
|
29
|
+
Requires-Dist: pyside6
|
|
30
|
+
Requires-Dist: pyside6-addons
|
|
28
31
|
Requires-Dist: python-docx
|
|
29
32
|
Requires-Dist: qtawesome
|
|
30
33
|
Requires-Dist: qtpy
|
|
@@ -14,12 +14,16 @@ from datetime import datetime
|
|
|
14
14
|
from math import sin, radians
|
|
15
15
|
from pathlib import Path, WindowsPath
|
|
16
16
|
|
|
17
|
-
import gemmi
|
|
17
|
+
import gemmi
|
|
18
|
+
|
|
19
|
+
if hasattr(gemmi, 'set_leak_warnings'):
|
|
20
|
+
gemmi.set_leak_warnings(False)
|
|
21
|
+
|
|
18
22
|
import requests
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
|
|
23
|
+
from qtpy import QtCore, QtGui, QtWebEngineWidgets, QtWidgets, compat
|
|
24
|
+
from qtpy.QtCore import Qt, QEvent
|
|
25
|
+
from qtpy.QtWidgets import (QMainWindow, QCheckBox, QListWidgetItem, QApplication,
|
|
26
|
+
QPlainTextEdit, QMessageBox, QScrollBar)
|
|
23
27
|
from gemmi import cif
|
|
24
28
|
|
|
25
29
|
from finalcif import VERSION
|
|
@@ -417,11 +421,12 @@ class AppWindow(QMainWindow):
|
|
|
417
421
|
def export_all_templates(self, filename: Path | None = None):
|
|
418
422
|
import pickle
|
|
419
423
|
if not filename:
|
|
420
|
-
filename, _ =
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
424
|
+
filename, _ = compat.getsavefilename(parent=self,
|
|
425
|
+
basedir=str(Path(self.get_last_workdir()).joinpath(
|
|
426
|
+
f'finalcif_templates_{time.strftime("%Y-%m-%d")}.dat')),
|
|
427
|
+
selectedfilter="Template File (*.dat)",
|
|
428
|
+
filters="Template File (*.dat)",
|
|
429
|
+
caption='Save templates')
|
|
425
430
|
if not filename:
|
|
426
431
|
return
|
|
427
432
|
templates = {'text' : self.export_raw_text_templates(),
|
|
@@ -440,10 +445,11 @@ class AppWindow(QMainWindow):
|
|
|
440
445
|
def import_all_templates(self, filename: Path | None = None):
|
|
441
446
|
import pickle
|
|
442
447
|
if not filename:
|
|
443
|
-
filename, _ =
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
448
|
+
filename, _ = compat.getopenfilename(parent=self,
|
|
449
|
+
basedir=self.get_last_workdir(),
|
|
450
|
+
selectedfilter="Template File (*.dat)",
|
|
451
|
+
filters="Template File (*.dat)",
|
|
452
|
+
caption='Save templates')
|
|
447
453
|
if not filename:
|
|
448
454
|
return
|
|
449
455
|
try:
|
|
@@ -495,7 +501,7 @@ class AppWindow(QMainWindow):
|
|
|
495
501
|
"""
|
|
496
502
|
Imports a text template from a CIF file.
|
|
497
503
|
"""
|
|
498
|
-
filename = cif_file_open_dialog()
|
|
504
|
+
filename = cif_file_open_dialog(parent=self)
|
|
499
505
|
if not filename:
|
|
500
506
|
return
|
|
501
507
|
try:
|
|
@@ -536,7 +542,8 @@ class AppWindow(QMainWindow):
|
|
|
536
542
|
if not filename.strip():
|
|
537
543
|
return
|
|
538
544
|
try:
|
|
539
|
-
|
|
545
|
+
write_options = cif.WriteOptions(cif.Style.Indent35)
|
|
546
|
+
doc.write_file(filename, options=write_options)
|
|
540
547
|
# Path(filename).write_text(doc.as_string(cif.Style.Indent35))
|
|
541
548
|
except PermissionError:
|
|
542
549
|
if Path(filename).is_dir():
|
|
@@ -1103,9 +1110,10 @@ class AppWindow(QMainWindow):
|
|
|
1103
1110
|
if file:
|
|
1104
1111
|
self.report_picture_path = Path(file)
|
|
1105
1112
|
else:
|
|
1106
|
-
filename, _ =
|
|
1107
|
-
|
|
1108
|
-
|
|
1113
|
+
filename, _ = compat.getopenfilename(parent=self,
|
|
1114
|
+
filters="Image Files (*.png *.jpg *.jpeg *.bmp "
|
|
1115
|
+
"*.gif *.tif *.tiff *.eps *.emf *.wmf)",
|
|
1116
|
+
caption='Open a Report Picture')
|
|
1109
1117
|
self.set_report_picture_path(filename)
|
|
1110
1118
|
|
|
1111
1119
|
def set_report_picture_path(self, filename: str):
|
|
@@ -1409,7 +1417,7 @@ class AppWindow(QMainWindow):
|
|
|
1409
1417
|
"""
|
|
1410
1418
|
imp_cif: CifContainer | None = None
|
|
1411
1419
|
if not filename:
|
|
1412
|
-
filename = cif_file_open_dialog(filter="CIF file (*.cif *.pcf *.cif_od *.cfx *.sqf)")
|
|
1420
|
+
filename = cif_file_open_dialog(parent=self, filter="CIF file (*.cif *.pcf *.cif_od *.cfx *.sqf)")
|
|
1413
1421
|
if not filename:
|
|
1414
1422
|
return
|
|
1415
1423
|
try:
|
|
@@ -1460,7 +1468,7 @@ class AppWindow(QMainWindow):
|
|
|
1460
1468
|
"""
|
|
1461
1469
|
self.ui.datanameComboBox.blockSignals(True)
|
|
1462
1470
|
if not filepath:
|
|
1463
|
-
filepath = Path(cif_file_open_dialog(last_dir=self.get_last_workdir()))
|
|
1471
|
+
filepath = Path(cif_file_open_dialog(parent=self, last_dir=self.get_last_workdir()))
|
|
1464
1472
|
if not filepath.is_file():
|
|
1465
1473
|
return
|
|
1466
1474
|
self.set_path_display_in_file_selector(str(filepath))
|
|
@@ -1669,7 +1677,7 @@ class AppWindow(QMainWindow):
|
|
|
1669
1677
|
self.load_cif_file(filepath=self.cif.fileobj, load_changes=False)
|
|
1670
1678
|
|
|
1671
1679
|
def get_file_from_dialog(self) -> Path | None:
|
|
1672
|
-
fp = cif_file_open_dialog(last_dir=self.get_last_workdir())
|
|
1680
|
+
fp = cif_file_open_dialog(parent=self, last_dir=self.get_last_workdir())
|
|
1673
1681
|
if not fp:
|
|
1674
1682
|
return None
|
|
1675
1683
|
filepath = Path(fp)
|
|
@@ -14,7 +14,7 @@ from html.parser import HTMLParser
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
16
|
import requests
|
|
17
|
-
from
|
|
17
|
+
from qtpy.QtCore import QThread, Signal
|
|
18
18
|
from requests.exceptions import MissingSchema
|
|
19
19
|
|
|
20
20
|
from finalcif.cif.cif_file_io import CifContainer
|
|
@@ -12,6 +12,10 @@ from contextlib import suppress
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
|
|
14
14
|
import gemmi
|
|
15
|
+
|
|
16
|
+
if hasattr(gemmi, 'set_leak_warnings'):
|
|
17
|
+
gemmi.set_leak_warnings(False)
|
|
18
|
+
|
|
15
19
|
from gemmi.cif import as_string, Document, Loop
|
|
16
20
|
from packaging.version import Version
|
|
17
21
|
from shelxfile import Shelxfile
|
|
@@ -207,18 +211,20 @@ class CifContainer:
|
|
|
207
211
|
return doc
|
|
208
212
|
|
|
209
213
|
def cif_as_string(self, without_hkl=False) -> str:
|
|
214
|
+
opt = gemmi.cif.WriteOptions(gemmi.cif.Style.Indent35)
|
|
215
|
+
|
|
210
216
|
if without_hkl:
|
|
211
217
|
# return a copy, do not delete hkl from original:
|
|
212
218
|
doc = gemmi.cif.Document()
|
|
213
|
-
doc.parse_string(self.doc.as_string(
|
|
219
|
+
doc.parse_string(self.doc.as_string(options=opt))
|
|
214
220
|
for block in doc:
|
|
215
221
|
if block.find_pair_item('_shelx_hkl_file'):
|
|
216
222
|
block.find_pair_item('_shelx_hkl_file').erase()
|
|
217
223
|
if block.find_pair_item('_shelx_fcf_file'):
|
|
218
224
|
block.find_pair_item('_shelx_fcf_file').erase()
|
|
219
|
-
return doc.as_string(
|
|
225
|
+
return doc.as_string(options=opt)
|
|
220
226
|
else:
|
|
221
|
-
return self.doc.as_string(
|
|
227
|
+
return self.doc.as_string(options=opt)
|
|
222
228
|
|
|
223
229
|
def __getitem__(self, item: str) -> str:
|
|
224
230
|
"""
|
|
@@ -712,13 +718,13 @@ class CifContainer:
|
|
|
712
718
|
x = self.block.find_loop('_atom_site_fract_x')
|
|
713
719
|
y = self.block.find_loop('_atom_site_fract_y')
|
|
714
720
|
z = self.block.find_loop('_atom_site_fract_z')
|
|
715
|
-
part = self.block.find_loop('_atom_site_disorder_group')
|
|
716
|
-
occ = self.block.find_loop('_atom_site_occupancy')
|
|
721
|
+
part = self.block.find_loop('_atom_site_disorder_group') or ('0',) * len(labels)
|
|
722
|
+
occ = self.block.find_loop('_atom_site_occupancy') or ('1.000000',) * len(labels)
|
|
717
723
|
u_eq = self.block.find_loop('_atom_site_U_iso_or_equiv')
|
|
718
724
|
atom = namedtuple('atom', ('label', 'type', 'x', 'y', 'z', 'part', 'occ', 'u_eq'))
|
|
719
725
|
for label, type, x, y, z, part, occ, u_eq in zip(labels, types, x, y, z,
|
|
720
|
-
part
|
|
721
|
-
occ
|
|
726
|
+
part,
|
|
727
|
+
occ,
|
|
722
728
|
u_eq, strict=True):
|
|
723
729
|
if without_h and self.ishydrogen(label):
|
|
724
730
|
continue
|
|
@@ -809,7 +815,7 @@ class CifContainer:
|
|
|
809
815
|
label2 = self.block.find_loop('_geom_bond_atom_site_label_2')
|
|
810
816
|
dist = self.block.find_loop('_geom_bond_distance')
|
|
811
817
|
symm = self.block.find_loop('_geom_bond_site_symmetry_2')
|
|
812
|
-
publ_loop = self.block.find_loop('_geom_bond_publ_flag')
|
|
818
|
+
publ_loop = self.block.find_loop('_geom_bond_publ_flag') or len(label1) * ['?']
|
|
813
819
|
bond = namedtuple('bond', ('label1', 'label2', 'dist', 'symm'))
|
|
814
820
|
for label1, label2, dist, symm, publ in zip(label1, label2, dist, symm, publ_loop):
|
|
815
821
|
if (without_h and (self.ishydrogen(label1) or self.ishydrogen(label2))) or self.yes_not_set(publ):
|
|
@@ -847,10 +853,10 @@ class CifContainer:
|
|
|
847
853
|
angle_val = self.block.find_loop('_geom_angle')
|
|
848
854
|
symm1 = self.block.find_loop('_geom_angle_site_symmetry_1')
|
|
849
855
|
symm2 = self.block.find_loop('_geom_angle_site_symmetry_3')
|
|
850
|
-
publ_loop = self.block.find_loop('_geom_angle_publ_flag')
|
|
856
|
+
publ_loop = self.block.find_loop('_geom_angle_publ_flag') or len(label1) * ['?']
|
|
851
857
|
angle = namedtuple('angle', ('label1', 'label2', 'label3', 'angle_val', 'symm1', 'symm2'))
|
|
852
858
|
for label1, label2, label3, angle_val, symm1, symm2, publ in \
|
|
853
|
-
|
|
859
|
+
zip(label1, label2, label3, angle_val, symm1, symm2, publ_loop, strict=True):
|
|
854
860
|
if ((without_H and (self.ishydrogen(label1) or self.ishydrogen(label2) or
|
|
855
861
|
self.ishydrogen(label3))) or (self.yes_not_set(publ))):
|
|
856
862
|
continue
|
|
@@ -892,14 +898,16 @@ class CifContainer:
|
|
|
892
898
|
symm2 = self.block.find_loop('_geom_torsion_site_symmetry_2')
|
|
893
899
|
symm3 = self.block.find_loop('_geom_torsion_site_symmetry_3')
|
|
894
900
|
symm4 = self.block.find_loop('_geom_torsion_site_symmetry_4')
|
|
895
|
-
publ_loop = self.block.find_loop('_geom_torsion_publ_flag')
|
|
901
|
+
publ_loop = self.block.find_loop('_geom_torsion_publ_flag') or len(label1) * ['?']
|
|
896
902
|
tors = namedtuple('Torsion',
|
|
897
903
|
('label1', 'label2', 'label3', 'label4', 'torsang', 'symm1', 'symm2', 'symm3', 'symm4'))
|
|
898
|
-
for label1, label2, label3, label4, torsang, symm1, symm2, symm3, symm4, publ in zip(label1, label2, label3,
|
|
904
|
+
for label1, label2, label3, label4, torsang, symm1, symm2, symm3, symm4, publ in zip(label1, label2, label3,
|
|
905
|
+
# noqa: B020
|
|
899
906
|
label4,
|
|
900
907
|
torsang, symm1, symm2,
|
|
901
908
|
symm3,
|
|
902
|
-
symm4, publ_loop,
|
|
909
|
+
symm4, publ_loop,
|
|
910
|
+
strict=True):
|
|
903
911
|
if ((without_h and (self.ishydrogen(label1) or self.ishydrogen(label2)
|
|
904
912
|
or self.ishydrogen(label3) or self.ishydrogen(label3))) or self.yes_not_set(publ)):
|
|
905
913
|
continue
|
|
@@ -918,11 +926,11 @@ class CifContainer:
|
|
|
918
926
|
dist_da = self.block.find_loop('_geom_hbond_distance_DA')
|
|
919
927
|
angle_dha = self.block.find_loop('_geom_hbond_angle_DHA')
|
|
920
928
|
symm = self.block.find_loop('_geom_hbond_site_symmetry_A')
|
|
921
|
-
publ_loop = self.block.find_loop('_geom_hbond_publ_flag')
|
|
929
|
+
publ_loop = self.block.find_loop('_geom_hbond_publ_flag') or len(label_d) * ['?']
|
|
922
930
|
hydr = namedtuple('HydrogenBond', ('label_d', 'label_h', 'label_a', 'dist_dh', 'dist_ha', 'dist_da',
|
|
923
931
|
'angle_dha', 'symm'))
|
|
924
932
|
for label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ in (
|
|
925
|
-
|
|
933
|
+
zip(label_d, label_h, label_a, dist_dh, dist_ha, dist_da, angle_dha, symm, publ_loop)):
|
|
926
934
|
if self.yes_not_set(publ):
|
|
927
935
|
continue
|
|
928
936
|
if self.picometer:
|
|
@@ -10,7 +10,7 @@ from pathlib import Path
|
|
|
10
10
|
from urllib.parse import urlparse
|
|
11
11
|
|
|
12
12
|
import requests
|
|
13
|
-
from
|
|
13
|
+
from qtpy.QtWidgets import QTableWidgetItem, QTextBrowser, QFrame
|
|
14
14
|
|
|
15
15
|
from finalcif.cif.cif_file_io import CifContainer
|
|
16
16
|
from finalcif.cif.cod.deposition_list import CODFetcher
|
|
@@ -210,7 +210,7 @@ class CODdeposit:
|
|
|
210
210
|
if f.authenticated:
|
|
211
211
|
self.token_valid = True
|
|
212
212
|
else:
|
|
213
|
-
self.ui.statusBar.showMessage('Unable to login. Check username/password.',
|
|
213
|
+
self.ui.statusBar.showMessage('Unable to login. Check username/password.', 12000)
|
|
214
214
|
f.get_table_data_by_token(self._cod_token)
|
|
215
215
|
parser = MyCODStructuresParser()
|
|
216
216
|
parser.feed(f.table_html)
|
|
@@ -346,14 +346,14 @@ class CODdeposit:
|
|
|
346
346
|
self.ui.depositionOptionsStackedWidget.setCurrentIndex(self.deposition_type_to_int(deposition_type))
|
|
347
347
|
|
|
348
348
|
def reset_deposit_button_state_to_initial(self):
|
|
349
|
-
self.ui.depositCIFpushButton.disconnect()
|
|
349
|
+
self.ui.depositCIFpushButton.clicked.disconnect()
|
|
350
350
|
self.ui.depositOutputTextBrowser.clear()
|
|
351
351
|
self.ui.depositCIFpushButton.setText("Deposit CIF")
|
|
352
352
|
self.ui.depositCIFpushButton.clicked.connect(self._init_deposit)
|
|
353
353
|
|
|
354
354
|
def set_deposit_button_to_try_again(self):
|
|
355
355
|
self.ui.depositCIFpushButton.setText("Try Again")
|
|
356
|
-
self.ui.depositCIFpushButton.disconnect()
|
|
356
|
+
self.ui.depositCIFpushButton.clicked.disconnect()
|
|
357
357
|
self.ui.depositCIFpushButton.clicked.connect(lambda: self.switch_to_page(self.deposition_type))
|
|
358
358
|
|
|
359
359
|
def log_response_text(self, resp: requests.Response, *args, **kwargs):
|
|
@@ -380,7 +380,7 @@ class CODdeposit:
|
|
|
380
380
|
self.user_email = text
|
|
381
381
|
|
|
382
382
|
def _set_external_hkl_file(self) -> None:
|
|
383
|
-
file = cif_file_open_dialog(filter="HKL file (*.hkl *.fcf)")
|
|
383
|
+
file = cif_file_open_dialog(parent=self, filter="HKL file (*.hkl *.fcf)")
|
|
384
384
|
if file.endswith('.hkl'):
|
|
385
385
|
if self.cif.res_file_data:
|
|
386
386
|
hklf = self.cif._hklf_number_from_shelxl_file()
|
|
@@ -5,6 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
import gemmi
|
|
6
6
|
import numpy as np
|
|
7
7
|
from gemmi.cif import Loop, Document, Style
|
|
8
|
+
from packaging import version
|
|
8
9
|
|
|
9
10
|
Limit = namedtuple('Limit', 'h_max, h_min, k_max, k_min, l_max, l_min')
|
|
10
11
|
|
|
@@ -30,7 +31,10 @@ class HKL:
|
|
|
30
31
|
|
|
31
32
|
@property
|
|
32
33
|
def hkl_as_cif(self) -> str:
|
|
33
|
-
|
|
34
|
+
if version.parse(gemmi.__version__) < version.parse('0.5.1'):
|
|
35
|
+
return self._doc.as_string(style=Style.Simple)
|
|
36
|
+
else:
|
|
37
|
+
return self._doc.as_string(options=gemmi.cif.WriteOptions(Style.Simple))
|
|
34
38
|
|
|
35
39
|
def _add_hkl_as_loop(self) -> None:
|
|
36
40
|
"""
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
##
|
|
7
7
|
################################################################################
|
|
8
8
|
|
|
9
|
-
from
|
|
9
|
+
from qtpy.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
|
|
10
10
|
QMetaObject, QObject, QPoint, QRect,
|
|
11
11
|
QSize, QTime, QUrl, Qt)
|
|
12
|
-
from
|
|
12
|
+
from qtpy.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
|
13
13
|
QFont, QFontDatabase, QGradient, QIcon,
|
|
14
14
|
QImage, QKeySequence, QLinearGradient, QPainter,
|
|
15
15
|
QPalette, QPixmap, QRadialGradient, QTransform)
|
|
16
|
-
from
|
|
16
|
+
from qtpy.QtWidgets import (QAbstractItemView, QApplication, QGridLayout, QHeaderView,
|
|
17
17
|
QLabel, QPushButton, QSizePolicy, QSpacerItem,
|
|
18
18
|
QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget)
|
|
19
19
|
|
|
@@ -19,7 +19,7 @@ class SHELXTlistfile(ParserMixin):
|
|
|
19
19
|
self.solutions = {}
|
|
20
20
|
self.parse_file()
|
|
21
21
|
|
|
22
|
-
def parse_file(self):
|
|
22
|
+
def parse_file(self) -> None:
|
|
23
23
|
"""
|
|
24
24
|
+ SHELXT - CRYSTAL STRUCTURE SOLUTION - VERSION 2018/2 +
|
|
25
25
|
"""
|
|
@@ -29,11 +29,15 @@ class SHELXTlistfile(ParserMixin):
|
|
|
29
29
|
if 'SHELXTL' in line:
|
|
30
30
|
self.version = 'SHELXT ' + line.split()[-1]
|
|
31
31
|
if line.strip().startswith('R1 Rweak Alpha'):
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
try:
|
|
33
|
+
for n in range(100):
|
|
34
|
+
if not self._text[num + 1 + n]:
|
|
35
|
+
break
|
|
36
|
+
if self._text[num + 1]:
|
|
37
|
+
self.solutions[self._text[num + 1 + n][58:76].strip()] = self._text[num + 1 + n][37:51].strip()
|
|
38
|
+
except IndexError:
|
|
39
|
+
return None
|
|
40
|
+
return None
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
class SolutionProgram:
|
|
@@ -58,17 +62,22 @@ class SolutionProgram:
|
|
|
58
62
|
except (TypeError, AttributeError):
|
|
59
63
|
res = ''
|
|
60
64
|
byxt = res.find('REM SHELXT solution in')
|
|
61
|
-
for x in xt_files:
|
|
62
|
-
shelxt = SHELXTlistfile(x.as_posix())
|
|
63
|
-
if shelxt.version and byxt:
|
|
64
|
-
self.method = 'direct'
|
|
65
|
-
self.solution_listfile = 'foo' # x.name
|
|
66
|
-
return shelxt
|
|
67
65
|
if byxt > 0:
|
|
66
|
+
for x in xt_files:
|
|
67
|
+
shelxt = SHELXTlistfile(x.as_posix())
|
|
68
|
+
if shelxt.version and byxt:
|
|
69
|
+
self.method = 'direct'
|
|
70
|
+
self.solution_listfile = 'foo' # x.name
|
|
71
|
+
return shelxt
|
|
68
72
|
xt = SHELXTlistfile('')
|
|
69
73
|
xt.version = "SHELXT (G. Sheldrick)"
|
|
70
74
|
self.method = 'direct'
|
|
71
75
|
return xt
|
|
76
|
+
if res.find('Best SHELXD solution'):
|
|
77
|
+
xt = SHELXTlistfile('')
|
|
78
|
+
xt.version = "SHELXD (G. Sheldrick)"
|
|
79
|
+
self.method = 'dual space'
|
|
80
|
+
return xt
|
|
72
81
|
xt = SHELXTlistfile('')
|
|
73
82
|
xt.version = "SHELXS (G. Sheldrick)"
|
|
74
83
|
self.method = 'direct'
|
|
@@ -5,9 +5,9 @@ from math import sqrt, cos, sin, dist
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
8
|
+
from qtpy import QtWidgets, QtCore, QtGui
|
|
9
|
+
from qtpy.QtCore import Qt
|
|
10
|
+
from qtpy.QtGui import QPainter, QPen, QBrush, QColor, QMouseEvent, QPalette, QImage, QResizeEvent, QWheelEvent
|
|
11
11
|
|
|
12
12
|
from finalcif.cif.atoms import get_radius_from_element, element2color
|
|
13
13
|
from finalcif.cif.cif_file_io import CifContainer
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
|
|
3
3
|
import vtk
|
|
4
|
-
from
|
|
5
|
-
from
|
|
4
|
+
from qtpy import QtWidgets, QtCore
|
|
5
|
+
from qtpy.QtGui import QSurfaceFormat
|
|
6
6
|
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
|
|
7
7
|
from vtkmodules.vtkCommonCore import vtkLookupTable
|
|
8
8
|
from vtkmodules.vtkDomainsChemistry import vtkPeriodicTable
|
|
@@ -13,7 +13,7 @@ from pathlib import Path
|
|
|
13
13
|
from typing import TYPE_CHECKING
|
|
14
14
|
|
|
15
15
|
import gemmi.cif
|
|
16
|
-
from
|
|
16
|
+
from qtpy.QtWidgets import QListWidgetItem
|
|
17
17
|
from gemmi.cif import Loop, as_string
|
|
18
18
|
|
|
19
19
|
from finalcif.cif.cif_file_io import CifContainer
|
|
@@ -59,6 +59,10 @@ class AuthorLoops:
|
|
|
59
59
|
f'{self.cif_key}_phone', f'{self.cif_key}_id_orcid', f'{self.cif_key}_id_iucr',
|
|
60
60
|
f'{self.cif_key}_footnote']
|
|
61
61
|
self.settings = FinalCifSettings()
|
|
62
|
+
try:
|
|
63
|
+
self._migrate_pyqt_saved_templates()
|
|
64
|
+
except ImportError as e:
|
|
65
|
+
print(f'Import of old settings failed:\n{e}')
|
|
62
66
|
if app:
|
|
63
67
|
self.ui.authorEditTabWidget.setCurrentIndex(0)
|
|
64
68
|
self.contact_author_checked(self.ui.ContactAuthorCheckBox.isChecked())
|
|
@@ -67,6 +71,30 @@ class AuthorLoops:
|
|
|
67
71
|
self.show_authors_list()
|
|
68
72
|
self.make_sure_to_save_only_when_name_field_has_text()
|
|
69
73
|
|
|
74
|
+
def _migrate_pyqt_saved_templates(self) -> None:
|
|
75
|
+
"""Author entries saved by PyQt5 (pre-v151) cannot be loaded by PySide2. Load such entries
|
|
76
|
+
using PyQt5 and re-save with PySide2.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
UPGRADE_FLAG = "v152_migrated_author_templates"
|
|
80
|
+
if self.settings.load_value_of_key(UPGRADE_FLAG):
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
import PyQt5.QtCore
|
|
84
|
+
pyqt_settings = PyQt5.QtCore.QSettings(self.settings.organization, self.settings.software_name)
|
|
85
|
+
|
|
86
|
+
pyqt_settings.beginGroup("authors_list")
|
|
87
|
+
for author in self.authors_list():
|
|
88
|
+
pyside_loopdata = self.author_loopdata(author)
|
|
89
|
+
pyqt_loopdata = pyqt_settings.value(author)
|
|
90
|
+
if not pyside_loopdata and isinstance(pyqt_loopdata, Author):
|
|
91
|
+
self.general_author_save(pyqt_loopdata)
|
|
92
|
+
print(f"Migrated pre-v151 saved author data for \"{author}\".")
|
|
93
|
+
pyqt_settings.endGroup()
|
|
94
|
+
|
|
95
|
+
self.settings.save_key_value(UPGRADE_FLAG, True)
|
|
96
|
+
del pyqt_settings
|
|
97
|
+
|
|
70
98
|
def connect_signals_and_slots(self) -> None:
|
|
71
99
|
self.ui.AddThisAuthorToLoopPushButton.clicked.connect(self.save_author_to_loop)
|
|
72
100
|
self.ui.AddThisAuthorToLoopPushButton_cif.clicked.connect(self.save_author_to_loop)
|
|
@@ -300,7 +328,7 @@ class AuthorLoops:
|
|
|
300
328
|
Import an author from a cif file.
|
|
301
329
|
"""
|
|
302
330
|
if not filename:
|
|
303
|
-
filename = cif_file_open_dialog(filter="CIF file (*.cif)")
|
|
331
|
+
filename = cif_file_open_dialog(parent=self.app, filter="CIF file (*.cif)")
|
|
304
332
|
if not filename:
|
|
305
333
|
return
|
|
306
334
|
doc = read_document_from_cif_file(filename)
|
|
@@ -4,8 +4,8 @@ from bisect import bisect
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
-
from
|
|
8
|
-
from
|
|
7
|
+
from qtpy import QtCore
|
|
8
|
+
from qtpy.QtWidgets import QListWidgetItem
|
|
9
9
|
from gemmi import cif
|
|
10
10
|
|
|
11
11
|
from finalcif.app_path import application_path
|
|
@@ -6,8 +6,8 @@ from contextlib import suppress
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
|
-
from
|
|
10
|
-
from
|
|
9
|
+
from qtpy import QtCore
|
|
10
|
+
from qtpy.QtWidgets import QListWidgetItem, QTableWidget, QStackedWidget, QLabel
|
|
11
11
|
from gemmi import cif
|
|
12
12
|
|
|
13
13
|
from finalcif.cif.text import retranslate_delimiter, utf8_to_str
|
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
# and you think this stuff is worth it, you can buy me a beer in return.
|
|
6
6
|
# Dr. Daniel Kratzert
|
|
7
7
|
# ----------------------------------------------------------------------------
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
os.environ['QT_API'] = 'pyside6'
|
|
8
11
|
import sys
|
|
9
12
|
import time
|
|
10
13
|
import traceback
|
|
11
14
|
from pathlib import Path
|
|
12
|
-
|
|
15
|
+
from qtpy.QtGui import QIcon
|
|
13
16
|
from finalcif import VERSION
|
|
14
17
|
from finalcif.app_path import application_path
|
|
15
18
|
from finalcif.appwindow import AppWindow, DEBUG, app
|
|
@@ -74,7 +77,6 @@ def main():
|
|
|
74
77
|
file = None
|
|
75
78
|
app.setQuitOnLastWindowClosed(True)
|
|
76
79
|
w = AppWindow(file=file)
|
|
77
|
-
from PySide6.QtGui import QIcon
|
|
78
80
|
app.setWindowIcon(QIcon(str(application_path / r'icon/finalcif2.png')))
|
|
79
81
|
w.setWindowTitle(f'FinalCif v{VERSION}')
|
|
80
82
|
# w.showMaximized() # For full screen view
|
|
@@ -2,9 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
from textwrap import wrap
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
from
|
|
7
|
-
from
|
|
5
|
+
from qtpy import QtCore, QtGui
|
|
6
|
+
from qtpy.QtCore import Qt, QObject, QEvent
|
|
7
|
+
from qtpy.QtWidgets import QComboBox, QSizePolicy
|
|
8
8
|
|
|
9
9
|
from finalcif.gui.validators import validators
|
|
10
10
|
|
|
@@ -3,10 +3,10 @@ from __future__ import annotations
|
|
|
3
3
|
import re
|
|
4
4
|
from enum import IntEnum
|
|
5
5
|
|
|
6
|
-
from
|
|
7
|
-
from
|
|
8
|
-
from
|
|
9
|
-
from
|
|
6
|
+
from qtpy import QtCore, QtGui
|
|
7
|
+
from qtpy.QtCore import QEvent, QObject, Qt
|
|
8
|
+
from qtpy.QtGui import QColor, QKeySequence, QBrush
|
|
9
|
+
from qtpy.QtWidgets import QAbstractScrollArea, QTableWidget, \
|
|
10
10
|
QTableWidgetItem, QWidget, QApplication, QHeaderView
|
|
11
11
|
|
|
12
12
|
from finalcif.cif.text import retranslate_delimiter
|