Source code for populse_mia.user_interface.data_browser.modify_table
# -*- coding: utf-8 -*-
"""
Module to handle updates of the databrowser table after modifications.
Contains:
Class:
- ModifyTable
"""
##########################################################################
# Populse_mia - Copyright (C) IRMaGe/CEA, 2018
# Distributed under the terms of the CeCILL license, as published by
# the CEA-CNRS-INRIA. Refer to the LICENSE file or to
# http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html
# for details.
##########################################################################
from datetime import datetime
# Populse_db imports
from populse_db.database import (
FIELD_TYPE_LIST_BOOLEAN,
FIELD_TYPE_LIST_DATE,
FIELD_TYPE_LIST_DATETIME,
FIELD_TYPE_LIST_FLOAT,
FIELD_TYPE_LIST_INTEGER,
FIELD_TYPE_LIST_STRING,
FIELD_TYPE_LIST_TIME,
)
# PyQt5 imports
from PyQt5.QtWidgets import (
QDialog,
QHBoxLayout,
QMessageBox,
QPushButton,
QTableWidget,
QTableWidgetItem,
QVBoxLayout,
)
# Populse_MIA imports
from populse_mia.data_manager.project import COLLECTION_CURRENT
[docs]
class ModifyTable(QDialog):
"""Used to modify the contents of cells which contains lists.
When the user wishes to modify a cell which contains a list in the
databrowser tab, a popup will appear to help the user to change the
content of the cell.
.. Methods:
- add_item: add one more element to self.value
- fill_table: fill the table
- rem_last_item: remove last element of self.value
- update_table_values: update the table in the database
"""
[docs]
def __init__(self, project, value, types, scans, tags):
"""
Initialization of the ModifyTable class
:param project: Instance of project
:param value: List of values of the cell
:param types: Value types
:param scans: Scans of the rows
:param tags: Tags of the columns
"""
super().__init__()
self.setModal(True)
# Variables init
self.types = types
self.scans = scans
self.tags = tags
self.project = project
self.value = value
# The table that will be filled
self.table = QTableWidget()
# Filling the table
self.fill_table()
# Ok button
ok_button = QPushButton("Ok")
ok_button.clicked.connect(self.update_table_values)
# Cancel button
cancel_button = QPushButton("Cancel")
cancel_button.clicked.connect(self.close)
# + button (add one more element to a list)
plus_button = QPushButton("+")
plus_button.setToolTip("Add one more element to the list")
plus_button.clicked.connect(self.add_item)
# - button (remove last element from a list)
minus_button = QPushButton("-")
minus_button.setToolTip("Remove the last element of the list")
minus_button.clicked.connect(self.rem_last_item)
# Layouts
self.v_box_final = QVBoxLayout()
self.h_box_final = QHBoxLayout()
self.h_box_final.addWidget(ok_button)
self.h_box_final.addWidget(cancel_button)
self.h_box_final.addWidget(plus_button)
self.h_box_final.addWidget(minus_button)
self.v_box_final.addWidget(self.table)
self.v_box_final.addLayout(self.h_box_final)
self.setLayout(self.v_box_final)
[docs]
def add_item(self):
"""Add one more element to self.value"""
self.value.append(0)
# Filling the table
self.fill_table()
[docs]
def fill_table(self):
"""Fill the table."""
# Sizes
self.table.setColumnCount(len(self.value))
self.table.setRowCount(1)
# Values filled
for i in range(0, self.table.columnCount()):
column_elem = self.value[i]
item = QTableWidgetItem()
item.setText(str(column_elem))
self.table.setItem(0, i, item)
# Resize
self.table.resizeColumnsToContents()
total_width = 0
total_height = 0
i = 0
while i < self.table.columnCount():
total_width += self.table.columnWidth(i)
total_height += self.table.rowHeight(i)
i += 1
if total_width + 20 < 900:
self.table.setFixedWidth(total_width + 20)
self.table.setFixedHeight(total_height + 25)
else:
self.table.setFixedWidth(900)
self.table.setFixedHeight(total_height + 40)
[docs]
def rem_last_item(self):
"""Remove last element of self.value"""
if len(self.value) > 1:
self.value.pop()
# Filling the table
self.fill_table()
else:
print(
"\nThe list must contain at least one element. "
"Deletion of the last element is aborted!\n"
)
[docs]
def update_table_values(self, test=False):
"""Update the table in the database when the 'OK' button is clicked."""
# import check_value_type only here to prevent circular import issue
from populse_mia.utils import check_value_type
valid = True
# For each value, type checked
for i in range(0, self.table.columnCount()):
item = self.table.item(0, i)
text = item.text()
valid_type = True
for tag_type in self.types:
if not check_value_type(text, tag_type, True):
valid_type = False
type_problem = tag_type
break
# Type checked
if not valid_type:
# Error dialog if invalid cell
valid = False
if test is False:
msg = QMessageBox()
msg.setIcon(QMessageBox.Warning)
msg.setText("Invalid value")
msg.setInformativeText(
"The value "
+ text
+ " is invalid with the type "
+ type_problem
)
msg.setWindowTitle("Warning")
msg.setStandardButtons(QMessageBox.Ok)
msg.buttonClicked.connect(msg.close)
msg.exec()
break
if valid:
# Database updated only if valid type for every cell
for cell in range(0, len(self.scans)):
scan = self.scans[cell]
tag = self.tags[cell]
tag_object = self.project.session.get_field(
COLLECTION_CURRENT, tag
)
tag_type = tag_object.field_type
database_value = []
# For each value
for i in range(0, self.table.columnCount()):
item = self.table.item(0, i)
text = item.text()
if tag_type == FIELD_TYPE_LIST_INTEGER:
database_value.append(int(text))
elif tag_type == FIELD_TYPE_LIST_FLOAT:
database_value.append(float(text))
elif tag_type == FIELD_TYPE_LIST_STRING:
database_value.append(str(text))
elif tag_type == FIELD_TYPE_LIST_BOOLEAN:
database_value.append(eval(text))
elif tag_type == FIELD_TYPE_LIST_DATE:
format = "%d/%m/%Y"
subvalue = datetime.strptime(text, format).date()
database_value.append(subvalue)
elif tag_type == FIELD_TYPE_LIST_DATETIME:
format = "%d/%m/%Y %H:%M:%S.%f"
subvalue = datetime.strptime(text, format)
database_value.append(subvalue)
elif tag_type == FIELD_TYPE_LIST_TIME:
format = "%H:%M:%S.%f"
subvalue = datetime.strptime(text, format).time()
database_value.append(subvalue)
# Database updated for every cell
self.project.session.set_value(
COLLECTION_CURRENT, scan, tag, database_value
)
self.close()