Fixed bug with resolution result facilitation if mistructured entities are returned.

Finalized entity & link imports from files.
This commit is contained in:
AccentuSoft
2022-01-16 22:44:46 +02:00
parent 6def4a6b0c
commit a65dd2b480
3 changed files with 310 additions and 63 deletions

View File

@@ -126,7 +126,7 @@ class EntitiesDB:
return returnValue
def addEntities(self, entsJsonList: list, fromServer: bool = False):
def addEntities(self, entsJsonList: Union[list, set, tuple], fromServer: bool = False):
self.dbLock.acquire()
returnValue = []

View File

@@ -332,10 +332,12 @@ class TabbedPane(QtWidgets.QTabWidget):
newNodeUIDs = []
for resultList in resolution_result:
newNodeJSON = resultList[0]
newNodeEntityType = newNodeJSON['Entity Type']
newNodeEntityType = newNodeJSON.get('Entity Type')
# Cannot assume proper order of dicts sent over the net.
newNodePrimaryFieldKey = self.mainWindow.RESOURCEHANDLER.getPrimaryFieldForEntityType(newNodeEntityType)
newNodePrimaryField = newNodeJSON[newNodePrimaryFieldKey]
newNodePrimaryField = newNodeJSON.get(newNodePrimaryFieldKey)
if not newNodeEntityType or not newNodePrimaryField:
continue
try:
# Attempt to get the index of an existing entity that shares primary field and type with the new
@@ -429,7 +431,8 @@ class TabbedPane(QtWidgets.QTabWidget):
self.addLinksToTabs(newLinks)
self.entityDB.resetTimeline()
def addLinksToTabs(self, newLinks, resolution_name: str = 'Entity Group') -> None:
def addLinksToTabs(self, newLinks, resolution_name: str = 'Entity Group',
linkGroupingOverride: bool = False) -> None:
for canvas in self.canvasTabs:
scene = self.canvasTabs[canvas].scene()
sceneChanged = False
@@ -463,8 +466,8 @@ class TabbedPane(QtWidgets.QTabWidget):
# Need to send this to server, since it won't be drawn otherwise.
scene.addLinkDragDrop(scene.nodesDict[parentUID], scene.nodesDict[uid], newLink[2])
if len(addedNodes) >= int(self.mainWindow.SETTINGS.value("Project/Resolution Result Grouping Threshold",
"15")):
if len(addedNodes) >= int(self.mainWindow.SETTINGS.value(
"Project/Resolution Result Grouping Threshold", "15")) and not linkGroupingOverride:
itemUIDs = [item.uid for item in addedNodes]
newGroupEntity = self.parent().entityDB.addEntity(
{'Group Name': resolution_name,

View File

@@ -298,7 +298,7 @@ class MenuBar(QtWidgets.QMenuBar):
def importFromFile(self) -> None:
importDialog = ImportFromFileDialog(self)
importDialogAccept = importDialog.exec_()
return_results = []
newNodes = []
newLinks = []
fileDirectory = Path(importDialog.fileDirectoryLine.text())
if importDialogAccept and fileDirectory != '':
@@ -330,8 +330,10 @@ class MenuBar(QtWidgets.QMenuBar):
for line in importFile:
lineValue = line.strip()
if lineValue:
return_results.append({primary_field: lineValue,
'Entity Type': selectedEntityType})
newEntityJSON = {primary_field: lineValue.strip(),
'Entity Type': selectedEntityType}
if newEntityJSON not in newNodes:
newNodes.append(newEntityJSON)
elif importDialog.CSVFileChoice.isChecked():
csvDF = pd.read_csv(fileDirectory)
@@ -346,6 +348,9 @@ class MenuBar(QtWidgets.QMenuBar):
if rowNumber < 2:
raise ValueError("Invalid CSV file data - Not enough rows.")
if len(csvDF.columns) < 1:
raise ValueError("Invalid CSV file data - Not enough columns.")
importEntityCSVDialog = ImportEntityFromCSVFile(self, csvDF)
if importEntityCSVDialog.exec_():
attributeRows = [comboBox.currentText()
@@ -360,10 +365,11 @@ class MenuBar(QtWidgets.QMenuBar):
entityTypeToImportAs = importEntityCSVDialog.entityTypeChoiceDropdown.currentText()
for row in csvDF.itertuples(index=False):
newEntityJSON = {str(attributeRows[key]): str(row[key])
newEntityJSON = {str(attributeRows[key]).strip(): str(row[key]).strip()
for key in range(len(attributeRows))}
newEntityJSON['Entity Type'] = entityTypeToImportAs
return_results.append(newEntityJSON)
if newEntityJSON not in newNodes:
newNodes.append(newEntityJSON)
elif importDialog.CSVFileChoiceLinks.isChecked():
csvDF = pd.read_csv(fileDirectory)
@@ -379,49 +385,157 @@ class MenuBar(QtWidgets.QMenuBar):
if rowNumber < 2:
raise ValueError("Invalid CSV file data - Not enough rows.")
if len(csvDF.columns) < 1:
raise ValueError("Invalid CSV file data - Not enough columns.")
importLinksCSVDialog = ImportLinksFromCSVFile(self, csvDF)
if importLinksCSVDialog.exec_():
entityOneType = importLinksCSVDialog.entityOneTypeChoiceDropdown.currentText()
entityTwoType = importLinksCSVDialog.entityTwoTypeChoiceDropdown.currentText()
unmapped = []
for columnIndex in range(len(importLinksCSVDialog.fieldMappingComboBoxes)):
columnMapping = importLinksCSVDialog.fieldMappingComboBoxes[columnIndex].currentText()
if columnMapping != '':
csvDF.rename(columns={csvDF.columns[columnIndex]: columnMapping}, inplace=True)
elif not importLinksCSVDialog.fieldIncludeCheckBoxes[columnIndex].isChecked():
unmapped.append(csvDF.columns[columnIndex])
for row in csvDF.itertuples(index=False):
count = 0
linkJSON = {}
entityOneJSON = {}
entityTwoJSON = {}
resolutionID = ""
notes = ""
if unmapped:
fieldsRemainingDF = csvDF[unmapped].copy()
for unmappedField in unmapped:
csvDF.drop(unmappedField, axis=1, inplace=True)
createLinkEntitiesDialog = ImportLinkEntitiesFromCSVFile(self, fieldsRemainingDF)
for column in row:
column = str(column)
mapping = importLinksCSVDialog.fieldMappingComboBoxes[count].currentText()
if mapping == 'Entity One':
entityOneJSON = self.parent().LENTDB.getEntityOfType(column, entityOneType)
elif mapping == 'Entity Two':
entityTwoJSON = self.parent().LENTDB.getEntityOfType(column, entityTwoType)
elif mapping == 'Notes':
notes = column
elif mapping == 'Resolution ID':
resolutionID = column
else:
linkJSON[csvDF.columns[count]] = column
count += 1
if createLinkEntitiesDialog.exec_():
entityOneType = importLinksCSVDialog.entityOneTypeChoiceDropdown.currentText()
entityTwoType = importLinksCSVDialog.entityTwoTypeChoiceDropdown.currentText()
if (entityOneJSON is not None) and (entityTwoJSON is not None):
linkJSON['uid'] = (entityOneJSON['uid'], entityTwoJSON['uid'])
linkJSON['Notes'] = notes
if importLinksCSVDialog.randAsIs.isChecked():
linkJSON['Resolution'] = resolutionID
elif importLinksCSVDialog.randMerge.isChecked():
linkJSON['Resolution'] = resolutionID + ' | ' + str(uuid4())
elif importLinksCSVDialog.randReplace.isChecked():
linkJSON['Resolution'] = str(uuid4())
attributeRows = [comboBox.currentText()
for comboBox in createLinkEntitiesDialog.fieldMappingComboBoxes]
for attribute in range(len(attributeRows)):
if attributeRows[attribute] == '':
attributeRows[attribute] = fieldsRemainingDF.columns[attribute]
self.parent().LENTDB.addLink(linkJSON)
newLinks.append((entityOneJSON['uid'], entityTwoJSON['uid'],
linkJSON['Resolution']))
entityTypeToImportAs = \
createLinkEntitiesDialog.entityTypeChoiceDropdown.currentText()
newNodeUIDs = [newEntity['uid'] for newEntity in self.parent().LENTDB.addEntities(return_results)]
newEntityPrimaryAttribute = \
self.parent().RESOURCEHANDLER.getPrimaryFieldForEntityType(entityTypeToImportAs)
for entityRow, linkRow in zip(fieldsRemainingDF.itertuples(index=False),
csvDF.itertuples(index=False)):
count = 0
linkJSON = {}
entityOneJSON = {}
entityTwoJSON = {}
resolutionID = ""
notes = ""
for column in linkRow:
column = str(column)
mapping = csvDF.columns[count]
if mapping == 'Entity One':
entityOneJSON = self.parent().LENTDB.getEntityOfType(column,
entityOneType)
elif mapping == 'Entity Two':
entityTwoJSON = self.parent().LENTDB.getEntityOfType(column,
entityTwoType)
elif mapping == 'Notes':
notes = column
elif mapping == 'Resolution ID':
resolutionID = column
else:
linkJSON[mapping] = column
count += 1
if (entityOneJSON is not None) and (entityTwoJSON is not None):
# linkJSON['uid'] = (entityOneJSON['uid'], entityTwoJSON['uid'])
linkJSON['Notes'] = notes
if importLinksCSVDialog.randAsIs.isChecked():
linkJSON['Resolution'] = resolutionID
elif importLinksCSVDialog.randMerge.isChecked():
linkJSON['Resolution'] = resolutionID + ' | ' + str(uuid4())
elif importLinksCSVDialog.randReplace.isChecked():
linkJSON['Resolution'] = str(uuid4())
# If 'Resolution ID' is not mapped, generate random IDs.
if not linkJSON.get('Resolution'):
linkJSON['Resolution'] = str(uuid4())
linkJSONOne = dict(linkJSON)
linkJSONOne['Resolution'] += ' OUT'
linkJSONTwo = dict(linkJSON)
linkJSONTwo['Resolution'] += ' IN'
linkJSONThree = dict(linkJSON)
newEntityJSON = {str(attributeRows[key]): str(entityRow[key]).strip()
for key in range(len(attributeRows))}
newEntityJSON['Entity Type'] = entityTypeToImportAs
newNode = self.parent().LENTDB.getEntityOfType(
newEntityJSON[newEntityPrimaryAttribute], entityTypeToImportAs)
if not newNode:
newNode = self.parent().LENTDB.addEntity(newEntityJSON,
updateTimeline=False)
linkJSONOne['uid'] = (entityOneJSON['uid'], newNode['uid'])
linkJSONTwo['uid'] = (newNode['uid'], entityTwoJSON['uid'])
linkJSONThree['uid'] = (entityOneJSON['uid'], entityTwoJSON['uid'])
self.parent().LENTDB.addLink(linkJSONOne)
self.parent().LENTDB.addLink(linkJSONTwo)
self.parent().LENTDB.addLink(linkJSONThree)
newLinks.append((entityOneJSON['uid'], newNode['uid'],
linkJSONOne['Resolution']))
newLinks.append((newNode['uid'], entityTwoJSON['uid'],
linkJSONTwo['Resolution']))
newLinks.append((entityOneJSON['uid'], entityTwoJSON['uid'],
linkJSONThree['Resolution']))
else:
entityOneType = importLinksCSVDialog.entityOneTypeChoiceDropdown.currentText()
entityTwoType = importLinksCSVDialog.entityTwoTypeChoiceDropdown.currentText()
for row in csvDF.itertuples(index=False):
count = 0
linkJSON = {}
entityOneJSON = {}
entityTwoJSON = {}
resolutionID = ""
notes = ""
for column in row:
column = str(column)
mapping = csvDF.columns[count]
if mapping == 'Entity One':
entityOneJSON = self.parent().LENTDB.getEntityOfType(column, entityOneType)
elif mapping == 'Entity Two':
entityTwoJSON = self.parent().LENTDB.getEntityOfType(column, entityTwoType)
elif mapping == 'Notes':
notes = column
elif mapping == 'Resolution ID':
resolutionID = column
else:
linkJSON[mapping] = column
count += 1
if (entityOneJSON is not None) and (entityTwoJSON is not None):
linkJSON['uid'] = (entityOneJSON['uid'], entityTwoJSON['uid'])
linkJSON['Notes'] = notes
if importLinksCSVDialog.randAsIs.isChecked():
linkJSON['Resolution'] = resolutionID
elif importLinksCSVDialog.randMerge.isChecked():
linkJSON['Resolution'] = resolutionID + ' | ' + str(uuid4())
elif importLinksCSVDialog.randReplace.isChecked():
linkJSON['Resolution'] = str(uuid4())
# If 'Resolution ID' is not mapped, generate random IDs.
if not linkJSON.get('Resolution'):
linkJSON['Resolution'] = str(uuid4())
self.parent().LENTDB.addLink(linkJSON)
newLinks.append((entityOneJSON['uid'], entityTwoJSON['uid'],
linkJSON['Resolution']))
newNodeUIDs = [newEntity['uid'] for newEntity in self.parent().LENTDB.addEntities(newNodes)]
if sceneToAddTo is not None:
for newNodeUID in newNodeUIDs:
@@ -430,7 +544,8 @@ class MenuBar(QtWidgets.QMenuBar):
sceneToAddTo.rearrangeGraph()
if newLinks:
self.parent().centralWidget().tabbedPane.addLinksToTabs(newLinks, 'File Links')
self.parent().centralWidget().tabbedPane.addLinksToTabs(newLinks, 'File Links',
linkGroupingOverride=True)
self.parent().LENTDB.resetTimeline()
except PermissionError:
@@ -587,7 +702,7 @@ class MenuBar(QtWidgets.QMenuBar):
def findEntityOrLink(self) -> None:
self.parent().findEntityOrLinkOnCanvas()
def openWebsite(self) -> None:
def openWebsite(self) -> None: # TODO: Expose this to the user
currentScene = self.parent().centralWidget().tabbedPane.getCurrentScene()
websites = [item.uid for item in currentScene.selectedItems()
if isinstance(item, BaseNode) and
@@ -830,16 +945,16 @@ class MenuBar(QtWidgets.QMenuBar):
projectFilesDir = Path(self.parent().SETTINGS.value("Project/FilesDir"))
"""
WARNING: This is a hackish solution that does not always work. Documentation and tools to work
with chrome and chromium session files are lacking last I checked,
WARNING: This is a hackish solution that does not always work. Documentation and tools to
work with chrome and chromium session files are lacking last I checked,
and most of the existing ones have been broken since the last update.
This is a best-effort solution for now, which should mostly work.
As for how it works, it's just pattern matching after some observations about the
file structure of chrome session files.
This will probably be revised in the future to make it actually parse chrome session
files.
This will probably be revised in the future to make it actually parse chrome
session files.
"""
httpTabs = re.split(b'http', chromeSessionFileContents)
for httpTab in httpTabs[1:]:
@@ -1278,6 +1393,7 @@ class ImportLinksFromCSVFile(QtWidgets.QDialog):
self.setModal(True)
importLayout = QtWidgets.QVBoxLayout()
self.setLayout(importLayout)
self.setWindowTitle("Import Links from CSV")
columnNumber = len(csvTableContents.columns)
@@ -1310,6 +1426,16 @@ class ImportLinksFromCSVFile(QtWidgets.QDialog):
entityTwoTypeChoiceLayout.addWidget(entityTwoTypeChoiceLabel)
entityTwoTypeChoiceLayout.addWidget(self.entityTwoTypeChoiceDropdown)
self.fieldIncludeCheckBoxes = []
tableFieldCheckBoxesWidget = QtWidgets.QWidget()
tableFieldCheckBoxesWidgetLayout = QtWidgets.QHBoxLayout()
tableFieldCheckBoxesWidget.setLayout(tableFieldCheckBoxesWidgetLayout)
for fieldIndex in range(columnNumber):
checkBoxWidget = QtWidgets.QCheckBox('Include Field? ')
checkBoxWidget.setToolTip('Check the box to include this column as an attribute for the resolution.')
self.fieldIncludeCheckBoxes.append(checkBoxWidget)
tableFieldCheckBoxesWidgetLayout.addWidget(checkBoxWidget)
self.fieldMappingComboBoxes = []
tableFieldAttributeMapping = QtWidgets.QWidget()
tableFieldAttributeMappingLayout = QtWidgets.QHBoxLayout()
@@ -1361,6 +1487,7 @@ class ImportLinksFromCSVFile(QtWidgets.QDialog):
importLayout.addWidget(entityTwoTypeChoiceWidget)
importLayout.addWidget(tableFieldAttributeMapping)
importLayout.addWidget(csvTable)
importLayout.addWidget(tableFieldCheckBoxesWidget)
importLayout.addWidget(randomizationLabel)
importLayout.addWidget(self.randAsIs)
importLayout.addWidget(self.randMerge)
@@ -1368,9 +1495,21 @@ class ImportLinksFromCSVFile(QtWidgets.QDialog):
importLayout.addWidget(buttonsWidget)
def changeMappingForField(self, newIndex):
for comboBox in self.fieldMappingComboBoxes:
if comboBox.currentIndex() == newIndex and not comboBox.hasFocus():
comboBox.setCurrentIndex(0)
for comboBoxIndex in range(len(self.fieldMappingComboBoxes)):
comboBox = self.fieldMappingComboBoxes[comboBoxIndex]
checkBox = self.fieldIncludeCheckBoxes[comboBoxIndex]
if comboBox.currentIndex() == newIndex:
if newIndex == 0:
checkBox.setEnabled(True)
else:
if comboBox.hasFocus():
checkBox.setEnabled(False)
checkBox.setChecked(True)
else:
comboBox.setCurrentIndex(0)
if newIndex != 0:
checkBox.setEnabled(True)
checkBox.setChecked(False)
def checkIfEntitiesAreMapped(self):
# Check if Entity One and Entity Two labels are assigned, do not proceed if not.
@@ -1384,8 +1523,106 @@ class ImportLinksFromCSVFile(QtWidgets.QDialog):
if isOneAssigned and isTwoAssigned:
self.accept()
else:
self.parent().parent().MESSAGEHANDLER.warning('Need to configure mappings for Entity One (parent) and '
'Entity Two (child) before proceeding.', popUp=True)
self.parent().parent().MESSAGEHANDLER.warning('Need to at least configure mappings for Entity One (parent) '
'and Entity Two (child) before proceeding.', popUp=True)
class ImportLinkEntitiesFromCSVFile(QtWidgets.QDialog):
def __init__(self, parent, csvTableContents: pd.DataFrame):
super(ImportLinkEntitiesFromCSVFile, self).__init__(parent=parent)
self.setStyleSheet(Stylesheets.MAIN_WINDOW_STYLESHEET)
self.setModal(True)
importLayout = QtWidgets.QVBoxLayout()
self.setLayout(importLayout)
self.setWindowTitle("Create Entities from Link Fields")
columnNumber = len(csvTableContents.columns)
titleLabel = QtWidgets.QLabel("Create Entities from Link Fields")
titleLabel.setAlignment(QtCore.Qt.AlignCenter)
descLabel = QtWidgets.QLabel("Select the entity type to import the remaining fields as. "
"Then, configure the mapping between the CSV fields and entity attributes. To do "
"so, select from the drop-down boxes the entity attributes that correspond to "
"each field in the CSV file. The drop-down boxes left blank will have the "
"corresponding CSV column names be treated as attribute names for the new "
"entities.")
descLabel.setWordWrap(True)
entityTypeChoiceWidget = QtWidgets.QWidget()
entityTypeChoiceLayout = QtWidgets.QHBoxLayout()
entityTypeChoiceWidget.setLayout(entityTypeChoiceLayout)
entityTypeChoiceLabel = QtWidgets.QLabel("Entity Type to Import As:")
self.entityTypeChoiceDropdown = QtWidgets.QComboBox()
self.entityTypeChoiceDropdown.setEditable(False)
self.entityTypeChoiceDropdown.addItems(parent.parent().RESOURCEHANDLER.getAllEntities())
self.entityTypeChoiceDropdown.currentIndexChanged.connect(self.pickEntityToImportAs)
entityTypeChoiceLayout.addWidget(entityTypeChoiceLabel)
entityTypeChoiceLayout.addWidget(self.entityTypeChoiceDropdown)
self.fieldMappingComboBoxes = []
tableFieldAttributeMapping = QtWidgets.QWidget()
tableFieldAttributeMappingLayout = QtWidgets.QHBoxLayout()
tableFieldAttributeMapping.setLayout(tableFieldAttributeMappingLayout)
for fieldIndex in range(columnNumber):
fieldMappingWidget = QtWidgets.QComboBox()
fieldMappingWidget.setEditable(False)
fieldMappingWidget.currentIndexChanged.connect(self.changeMappingForField)
fieldMappingWidget.addItem('')
self.fieldMappingComboBoxes.append(fieldMappingWidget)
tableFieldAttributeMappingLayout.addWidget(fieldMappingWidget)
csvTable = QtWidgets.QTableWidget(3, columnNumber, self)
csvTable.setHorizontalHeaderLabels(csvTableContents.columns)
for row in csvTableContents[:3].itertuples():
rowValues = list(row)
for column in range(columnNumber):
columnItem = QtWidgets.QTableWidgetItem(str(rowValues[column + 1]))
columnItem.setFlags(columnItem.flags() & ~QtCore.Qt.ItemIsEditable)
csvTable.setItem(rowValues[0], column, columnItem)
buttonsWidget = QtWidgets.QWidget()
buttonsWidgetLayout = QtWidgets.QHBoxLayout()
buttonsWidget.setLayout(buttonsWidgetLayout)
confirmButton = QtWidgets.QPushButton('Confirm')
cancelButton = QtWidgets.QPushButton('Cancel')
buttonsWidgetLayout.addWidget(cancelButton)
buttonsWidgetLayout.addWidget(confirmButton)
cancelButton.clicked.connect(self.reject)
confirmButton.clicked.connect(self.confirmThatPrimaryFieldIsMapped)
importLayout.addWidget(titleLabel)
importLayout.addWidget(descLabel)
importLayout.addWidget(entityTypeChoiceWidget)
importLayout.addWidget(tableFieldAttributeMapping)
importLayout.addWidget(csvTable)
importLayout.addWidget(buttonsWidget)
self.pickEntityToImportAs()
def pickEntityToImportAs(self):
currentEntityAttributes = [''] + self.parent().parent().RESOURCEHANDLER.getEntityAttributes(
self.entityTypeChoiceDropdown.currentText())
for comboBox in self.fieldMappingComboBoxes:
comboBox.clear()
comboBox.addItems(currentEntityAttributes)
def changeMappingForField(self, newIndex):
for comboBox in self.fieldMappingComboBoxes:
if comboBox.currentIndex() == newIndex and not comboBox.hasFocus():
comboBox.setCurrentIndex(0)
def confirmThatPrimaryFieldIsMapped(self):
primaryField = self.parent().parent().RESOURCEHANDLER.getPrimaryFieldForEntityType(
self.entityTypeChoiceDropdown.currentText())
for comboBox in self.fieldMappingComboBoxes:
if comboBox.currentText() == primaryField:
self.accept()
self.parent().parent().MESSAGEHANDLER.warning('Primary field (' + primaryField +
') needs to be mapped before proceeding.')
class ImportEntityFromCSVFile(QtWidgets.QDialog):
@@ -1397,6 +1634,7 @@ class ImportEntityFromCSVFile(QtWidgets.QDialog):
self.setModal(True)
importLayout = QtWidgets.QVBoxLayout()
self.setLayout(importLayout)
self.setWindowTitle("Import Entities from CSV")
columnNumber = len(csvTableContents.columns)
@@ -1493,16 +1731,22 @@ class ImportEntityFromCSVFile(QtWidgets.QDialog):
def confirmThatPrimaryFieldIsMapped(self):
primaryField = self.parent().parent().RESOURCEHANDLER.getPrimaryFieldForEntityType(
self.entityTypeChoiceDropdown.currentText())
primaryFieldMapped = False
for comboBox in self.fieldMappingComboBoxes:
if comboBox.currentText() == primaryField:
self.accept()
self.parent().parent().MESSAGEHANDLER.warning('Primary field (' + primaryField +
') needs to be mapped before proceeding.')
# Executing self.accept() will not actually end the prompt, so we use bools to check and confirm.
primaryFieldMapped = True
break
if primaryFieldMapped:
self.accept()
else:
self.parent().parent().MESSAGEHANDLER.warning('Primary field (' + primaryField +
') needs to be mapped before proceeding.')
class ImportFromFileDialog(QtWidgets.QDialog):
def popupFileDialog(self):
self.fileDirectory = QtWidgets.QFileDialog().getOpenFileName(parent=self, caption='Select file to import',
self.fileDirectory = QtWidgets.QFileDialog().getOpenFileName(parent=self, caption='Select File to Import From',
dir=str(Path.home()),
options=QtWidgets.QFileDialog.DontUseNativeDialog,
filter="CSV or txt (*.csv *.txt)")[0]
@@ -1512,7 +1756,7 @@ class ImportFromFileDialog(QtWidgets.QDialog):
def __init__(self, parent):
super(ImportFromFileDialog, self).__init__(parent=parent)
self.fileDirectory = ''
self.setWindowTitle('Import Entities From Text File')
self.setWindowTitle('Import Entities From File')
self.setModal(True)
dialogLayout = QtWidgets.QGridLayout()