CS4820-Winter2020 student project to create a COUNTER SUSHI R5 harvester and related functionality app for Windows and Mac
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.

243 lines
11 KiB

5 years ago
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')