You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
11 KiB
242 lines
11 KiB
import csv |
|
import os |
|
import shlex |
|
import sip |
|
import json |
|
from PyQt5.QtCore import QDate |
|
from PyQt5.QtWidgets import QFrame, QVBoxLayout, QComboBox, QLineEdit, QFileDialog |
|
|
|
import ManageDB |
|
import DataStorage |
|
from ui import MainWindow, SearchAndClauseFrame, SearchOrClauseFrame |
|
|
|
|
|
class SearchController: |
|
def __init__(self, main_window_ui: MainWindow.Ui_mainWindow): |
|
self.main_window = main_window_ui |
|
|
|
# set up report types combobox |
|
self.report_parameter = main_window_ui.search_report_parameter_combobox |
|
self.report_parameter.addItems(ManageDB.DATABASE_REPORTS) |
|
self.report_parameter.addItems(ManageDB.ITEM_REPORTS) |
|
self.report_parameter.addItems(ManageDB.PLATFORM_REPORTS) |
|
self.report_parameter.addItems(ManageDB.TITLE_REPORTS) |
|
|
|
# set up start year dateedit |
|
self.start_year_parameter = main_window_ui.search_start_year_parameter_dateedit |
|
self.start_year_parameter.setDate(QDate.currentDate()) |
|
|
|
# set up end year dateedit |
|
self.end_year_parameter = main_window_ui.search_end_year_parameter_dateedit |
|
self.end_year_parameter.setDate(QDate.currentDate()) |
|
|
|
# set up search button |
|
self.search_button = main_window_ui.search_button |
|
self.search_button.clicked.connect(self.search) |
|
|
|
self.open_results_checkbox = main_window_ui.search_open_results_checkbox |
|
|
|
# set up export button |
|
self.export_button = main_window_ui.search_export_button |
|
self.export_button.clicked.connect(self.export_parameters) |
|
|
|
# set up import button |
|
self.import_button = main_window_ui.search_import_button |
|
self.import_button.clicked.connect(self.import_parameters) |
|
|
|
# set up restore database button |
|
self.restore_database_button = main_window_ui.search_restore_database_button |
|
self.restore_database_button.clicked.connect(self.restore_database) |
|
|
|
# set up add and clause button |
|
def add_and_and_or_clause(): |
|
and_clause = self.add_and_clause() |
|
self.add_or_clause(and_clause) |
|
|
|
self.add_and_button = main_window_ui.search_add_and_button |
|
self.add_and_button.clicked.connect(add_and_and_or_clause) |
|
|
|
# resets the search clauses when the report type is changed |
|
def refresh_and_add_clauses(): |
|
self.refresh_clauses() |
|
add_and_and_or_clause() |
|
self.report_parameter.currentTextChanged.connect(refresh_and_add_clauses) |
|
|
|
self.and_clause_parameters = None |
|
refresh_and_add_clauses() |
|
|
|
def refresh_clauses(self): # resets the search clauses |
|
self.and_clause_parameters = QFrame() |
|
self.and_clause_parameters.setLayout(QVBoxLayout()) |
|
self.main_window.search_and_clause_parameters_scrollarea.setWidget(self.and_clause_parameters) |
|
|
|
def add_and_clause(self): |
|
and_clause = QFrame() |
|
and_clause_ui = SearchAndClauseFrame.Ui_search_and_clause_parameter_frame() |
|
and_clause_ui.setupUi(and_clause) |
|
|
|
# set up add or clause button |
|
def add_or_to_this_and(): |
|
self.add_or_clause(and_clause_ui) |
|
|
|
and_clause_ui.search_add_or_clause_button.clicked.connect(add_or_to_this_and) |
|
|
|
# set up remove current and clause button |
|
def remove_this_and(): |
|
self.and_clause_parameters.layout().removeWidget(and_clause) |
|
sip.delete(and_clause) |
|
|
|
and_clause_ui.search_remove_and_clause_button.clicked.connect(remove_this_and) |
|
|
|
# add to the layout |
|
self.and_clause_parameters.layout().addWidget(and_clause) |
|
|
|
return and_clause_ui |
|
|
|
def add_or_clause(self, and_clause): |
|
or_clause = QFrame() |
|
or_clause_ui = SearchOrClauseFrame.Ui_search_or_clause_parameter_frame() |
|
or_clause_ui.setupUi(or_clause) |
|
|
|
# fill field combobox |
|
field_combobox = or_clause_ui.search_field_parameter_combobox |
|
for field in ManageDB.get_report_fields_list(self.report_parameter.currentText(), True): |
|
if 'calculation' not in field.keys() and field['name'] not in ManageDB.FIELDS_NOT_IN_SEARCH: |
|
field_combobox.addItem(field['name']) |
|
|
|
# TODO make value check for type |
|
|
|
# fill comparison operator combobox |
|
comparison_combobox = or_clause_ui.search_comparison_parameter_combobox |
|
comparison_combobox.addItems(('=', '<=', '<', '>=', '>', 'LIKE')) |
|
|
|
# set up remove current or clause button |
|
def remove_this_or(): |
|
and_clause.search_or_clause_parameters_frame.layout().removeWidget(or_clause) |
|
sip.delete(or_clause) |
|
|
|
or_clause_ui.search_remove_or_clause_button.clicked.connect(remove_this_or) |
|
|
|
# add to parent and clause's layout |
|
and_clause.search_or_clause_parameters_frame.layout().addWidget(or_clause) |
|
|
|
return or_clause_ui |
|
|
|
def export_parameters(self): # export current search parameters to selected file |
|
parameters = self.get_search_parameters() |
|
print(parameters) |
|
dialog = QFileDialog() |
|
dialog.setFileMode(QFileDialog.AnyFile) |
|
dialog.setAcceptMode(QFileDialog.AcceptSave) |
|
dialog.setNameFilter('JSON files (*.dat)') |
|
if dialog.exec_(): |
|
file_name = dialog.selectedFiles()[0] |
|
if file_name[-4:].lower() != '.dat' and file_name != '': |
|
file_name += '.tsv' |
|
file = open(file_name, 'w', encoding='utf-8') |
|
if file.mode == 'w': |
|
json.dump(parameters, file) |
|
|
|
def import_parameters(self): # import search parameters from selected file |
|
dialog = QFileDialog() |
|
dialog.setFileMode(QFileDialog.ExistingFile) |
|
dialog.setNameFilter('JSON files (*.dat)') |
|
if dialog.exec_(): |
|
fields = json.loads(DataStorage.read_json_file(dialog.selectedFiles()[0])) |
|
print(fields) |
|
self.report_parameter.setCurrentText(fields['report']) |
|
self.start_year_parameter.setDate(QDate(fields['start_year'], 1, 1)) |
|
self.end_year_parameter.setDate(QDate(fields['end_year'], 1, 1)) |
|
clauses = fields['search_parameters'] |
|
print(clauses) |
|
self.refresh_clauses() |
|
for clause in clauses: |
|
and_clause = self.add_and_clause() |
|
for sub_clause in clause: |
|
or_clause = self.add_or_clause(and_clause) |
|
or_clause.search_field_parameter_combobox.setCurrentText(sub_clause['field']) |
|
or_clause.search_comparison_parameter_combobox.setCurrentText(sub_clause['comparison']) |
|
or_clause.search_value_parameter_lineedit.setText(sub_clause['value']) |
|
|
|
def search(self): # submit search result to database and open results |
|
parameters = self.get_search_parameters() |
|
|
|
# sql query to get search results |
|
sql_text = ManageDB.search_sql_text(parameters['report'], parameters['start_year'], |
|
parameters['end_year'], parameters['search_parameters']) |
|
print(sql_text) # testing |
|
|
|
headers = [] |
|
for field in ManageDB.get_report_fields_list(parameters['report'], True): |
|
headers.append(field['name']) |
|
|
|
dialog = QFileDialog() |
|
dialog.setFileMode(QFileDialog.AnyFile) |
|
dialog.setAcceptMode(QFileDialog.AcceptSave) |
|
dialog.setNameFilter('TSV files (*.tsv)') |
|
if dialog.exec_(): |
|
file_name = dialog.selectedFiles()[0] |
|
if file_name[-4:].lower() != '.tsv' and file_name != '': |
|
file_name += '.tsv' |
|
connection = ManageDB.create_connection(ManageDB.DATABASE_LOCATION) |
|
if connection is not None: |
|
results = ManageDB.run_select_sql(connection, sql_text) |
|
results.insert(0, headers) |
|
print(results) |
|
file = open(file_name, 'w', newline="", encoding='utf-8') |
|
if file.mode == 'w': |
|
output = csv.writer(file, delimiter='\t', quotechar='\"') |
|
for row in results: |
|
output.writerow(row) |
|
|
|
open_file_switcher = {'nt': (lambda: os.startfile(file_name)), |
|
# TODO check file_name for special characters and quote |
|
'posix': (lambda: os.system("open " + shlex.quote(file_name)))} |
|
if self.open_results_checkbox.isChecked(): |
|
open_file_switcher[os.name]() |
|
else: |
|
print('Error: could not open file ' + file_name) |
|
|
|
connection.close() |
|
else: |
|
print('Error, no connection') |
|
else: |
|
print('Error, no file location selected') |
|
|
|
def get_search_parameters(self): |
|
# get report type |
|
report = self.report_parameter.currentText() |
|
# get start year |
|
start_year = int(self.start_year_parameter.text()) |
|
# get end year |
|
end_year = int(self.end_year_parameter.text()) |
|
|
|
search_parameters = [] |
|
for and_widget in self.and_clause_parameters.findChildren(QFrame, 'search_and_clause_parameter_frame'): |
|
# iterate over and clauses |
|
print('and: ' + str(and_widget.objectName()) + ' ' + str(and_widget)) # testing |
|
or_clause_parameters = and_widget.findChild(QFrame, 'search_or_clause_parameters_frame') |
|
or_clauses = [] |
|
for or_widget in or_clause_parameters.findChildren(QFrame, 'search_or_clause_parameter_frame'): |
|
# iterate over child or clauses |
|
print('\tor: ' + str(or_widget.objectName()) + ' ' + str(or_widget)) # testing |
|
# get parameters for clause |
|
field_parameter = or_widget.findChild(QComboBox, 'search_field_parameter_combobox').currentText() |
|
comparison_parameter = or_widget.findChild(QComboBox, |
|
'search_comparison_parameter_combobox').currentText() |
|
value_parameter = or_widget.findChild(QLineEdit, 'search_value_parameter_lineedit').text() |
|
# TODO check for special characters |
|
or_clauses.append( |
|
{'field': field_parameter, 'comparison': comparison_parameter, 'value': value_parameter}) |
|
search_parameters.append(or_clauses) |
|
|
|
return {'report': report, 'start_year': start_year, 'end_year': end_year, |
|
'search_parameters': search_parameters} |
|
|
|
def restore_database(self): |
|
ManageDB.setup_database(True) |
|
reports = ManageDB.get_all_reports() |
|
for report in reports: |
|
print(os.path.basename(report['file'])) |
|
ManageDB.insert_single_file(report['file'], report['vendor'], report['year']) |
|
print('done')
|
|
|