Browse Source

Master Branch Merge

master 1
Adam McGuigan 5 years ago
commit
6150f9cd92
  1. 134
      .gitignore
  2. 609
      Constants.py
  3. 293
      Costs.py
  4. 25
      DataStorage.py
  5. 3067
      FetchData.py
  6. 140
      GeneralUtils.py
  7. 284
      ImportFile.py
  8. 3
      JsonUtils.py
  9. 144
      MainDriver.py
  10. 1071
      ManageDB.py
  11. 648
      ManageVendors.py
  12. 11
      PyToExecutable.py
  13. 75
      README.md
  14. 21
      Resources.qrc
  15. 5902
      Resources_rc.py
  16. 301
      Search.py
  17. 213
      Settings.py
  18. 757
      Visual.py
  19. 1
      _config.yml
  20. 89
      dev_notes.md
  21. 7
      docs/Constants.py.rst
  22. 7
      docs/Costs.py.rst
  23. 7
      docs/FetchData.py.rst
  24. 7
      docs/GeneralUtils.py.rst
  25. 7
      docs/ImportFile.py.rst
  26. 7
      docs/MainDriver.py.rst
  27. 20
      docs/Makefile
  28. 7
      docs/ManageDB.py.rst
  29. 7
      docs/ManageVendors.py.rst
  30. 7
      docs/Search.py.rst
  31. 7
      docs/Settings.py.rst
  32. 7
      docs/Visual.py.rst
  33. 58
      docs/conf.py
  34. 31
      docs/index.rst
  35. 35
      docs/make.bat
  36. 26
      docs/pyinstaller-how-to.md
  37. BIN
      executables/Linux/Counter 5 Report Tool.zip
  38. BIN
      executables/Windows/COUNTER 5 Report Tool.zip
  39. BIN
      executables/macOS/Counter 5 Report Tool.zip
  40. BIN
      images/CostsHelp.png
  41. BIN
      images/FetchReportsHelp.png
  42. BIN
      images/FetchSpecialReportsHelp.png
  43. BIN
      images/ManageVendorsHelp.png
  44. BIN
      images/SearchHelp.png
  45. BIN
      images/SettingsHelp.PNG
  46. BIN
      images/VisualHelp.png
  47. BIN
      images/importReportsHelp.png
  48. BIN
      main_icon.ico
  49. 13
      requirements.txt
  50. 0
      tests/data/test_file_for_import.tsv
  51. 34
      tests/test_AddVendorDialog.py
  52. 53
      tests/test_CostsTab.py
  53. 22
      tests/test_DisclaimerDialog.py
  54. 28
      tests/test_FetchProgressDialog.py
  55. 50
      tests/test_FetchReportsTab.py
  56. 43
      tests/test_FetchSpecialReportsTab.py
  57. 184
      tests/test_ImportFile.py
  58. 35
      tests/test_ImportReportTab.py
  59. 160
      tests/test_MainWindow.py
  60. 53
      tests/test_ManageVendorsTab.py
  61. 22
      tests/test_MessageDialog.py
  62. 23
      tests/test_RemoveVendorDialog.py
  63. 28
      tests/test_ReportResultWidget.py
  64. 26
      tests/test_ReportTypeDialog.py
  65. 19
      tests/test_SearchAndFrame.py
  66. 26
      tests/test_SearchOrFrame.py
  67. 44
      tests/test_SearchTab.py
  68. 56
      tests/test_SettingTab.py
  69. 30
      tests/test_UpdateDatabaseProgressDialog.py
  70. 24
      tests/test_VendorResultsWidget.py
  71. 65
      tests/test_VisualTab.py
  72. 146
      ui/AddVendorDialog.py
  73. 221
      ui/AddVendorDialog.ui
  74. 158
      ui/CostsTab.py
  75. 289
      ui/CostsTab.ui
  76. 39
      ui/DisclaimerDialog.py
  77. 97
      ui/DisclaimerDialog.ui
  78. 80
      ui/FetchProgressDialog.py
  79. 113
      ui/FetchProgressDialog.ui
  80. 113
      ui/FetchProgressDialog_bak.ui
  81. 422
      ui/FetchReportsTab.py
  82. 801
      ui/FetchReportsTab.ui
  83. 360
      ui/FetchSpecialReportsTab.py
  84. 633
      ui/FetchSpecialReportsTab.ui
  85. 208
      ui/ImportReportTab.py
  86. 352
      ui/ImportReportTab.ui
  87. 58
      ui/MainWindow.py
  88. 83
      ui/MainWindow.ui
  89. 262
      ui/ManageVendorsTab.py
  90. 419
      ui/ManageVendorsTab.ui
  91. 37
      ui/MessageDialog.py
  92. 43
      ui/MessageDialog.ui
  93. 33
      ui/RemoveVendorDialog.py
  94. 45
      ui/RemoveVendorDialog.ui
  95. 192
      ui/ReportResultWidget.py
  96. 356
      ui/ReportResultWidget.ui
  97. 44
      ui/ReportTypeDialog.py
  98. 67
      ui/ReportTypeDialog.ui
  99. 71
      ui/SearchAndClauseFrame.py
  100. 76
      ui/SearchAndClauseFrame.ui
  101. Some files were not shown because too many files have changed in this diff Show More

134
.gitignore vendored

@ -0,0 +1,134 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# Custom
.idea/
all_data/
.DS_Store

609
Constants.py

@ -0,0 +1,609 @@
from enum import Enum
# Variable Constants for MainDriver.py
HELP_SITE = "https://git.library.upei.ca/mbelvadi/COUNTER-5-Report-Tool/wiki"
# region Variable Constants for ManageDB
# region field and table definitions
# region dictionary keys
NAME_KEY = 'name'
TYPE_KEY = 'type'
OPTIONS_KEY = 'options'
REPORTS_KEY = 'reports'
CALCULATION_KEY = 'calculation'
SOURCE_KEY = 'source'
FIELD_KEY = 'field'
COMPARISON_KEY = 'comparison'
VALUE_KEY = 'value'
# endregion
# region header definition
HEADER_ENTRIES = ('report_name', 'report_id', 'release', 'institution_name', 'institution_id', 'metric_types',
'report_filters', 'report_attributes', 'exceptions', 'reporting_period', 'created', 'created_by')
HEADER_ROWS = len(HEADER_ENTRIES)
BLANK_ROWS = 1
# endregion
# region database report definitions
DATABASE_REPORTS = ('DR', 'DR_D1', 'DR_D2')
DATABASE_REPORTS_METRIC = ('Searches_Automated',
'Searches_Federated',
'Searches_Regular',
'Total_Item_Investigations',
'Total_Item_Requests',
'Unique_Item_Investigations',
'Unique_Item_Requests',
'Unique_Title_Investigations',
'Unique_Title_Requests',
'Limit_Exceeded',
'No_License')
DATABASE_REPORTS_ATTRIBUTES = ("Data_Type",
"Access_Method")
DATABASE_REPORT_FIELDS = ({NAME_KEY: 'database',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('DR', 'DR_D1', 'DR_D2')},
{NAME_KEY: 'publisher',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('DR', 'DR_D1', 'DR_D2')},
{NAME_KEY: 'publisher_id',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('DR', 'DR_D1', 'DR_D2')},
{NAME_KEY: 'platform',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('DR', 'DR_D1', 'DR_D2')},
{NAME_KEY: 'proprietary_id',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('DR', 'DR_D1', 'DR_D2')},
{NAME_KEY: 'data_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('DR',)},
{NAME_KEY: 'access_method',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('DR',)})
# endregion
# region item report definitions
ITEM_REPORTS = ('IR', 'IR_A1', 'IR_M1')
ITEM_REPORTS_METRIC = ('Total_Item_Investigations',
'Total_Item_Requests',
'Unique_Item_Investigations',
'Unique_Item_Requests',
'Limit_Exceeded',
'No_License')
ITEM_REPORTS_ATTRIBUTES = ("Data_Type",
"Access_Type",
"Access_Method",
"YOP",
"Authors",
"Publication_Date",
"Article_Version")
ITEM_REPORT_FIELDS = ({NAME_KEY: 'item',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1', 'IR_M1')},
{NAME_KEY: 'publisher',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1', 'IR_M1')},
{NAME_KEY: 'publisher_id',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1', 'IR_M1')},
{NAME_KEY: 'platform',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1', 'IR_M1')},
{NAME_KEY: 'authors',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'publication_date',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'doi',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1', 'IR_M1')},
{NAME_KEY: 'proprietary_id',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1', 'IR_M1')},
{NAME_KEY: 'isbn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'print_issn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'online_issn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'uri',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1', 'IR_M1')},
{NAME_KEY: 'parent_title',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'parent_authors',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'parent_publication_date',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'parent_article_version',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'parent_data_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'parent_doi',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'parent_proprietary_id',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'parent_isbn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'parent_print_issn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'parent_online_issn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'parent_uri',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'component_title',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_authors',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_publication_date',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_data_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_doi',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_proprietary_id',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_isbn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_print_issn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_online_issn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'component_uri',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'data_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'yop',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)},
{NAME_KEY: 'access_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR', 'IR_A1')},
{NAME_KEY: 'access_method',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('IR',)})
# endregion
# region platform report definitions
PLATFORM_REPORTS = ('PR', 'PR_P1')
PLATFORM_REPORTS_METRIC = ('Searches_Platform',
'Total_Item_Investigations',
'Total_Item_Requests',
'Unique_Item_Investigations',
'Unique_Item_Requests',
'Unique_Title_Investigations',
'Unique_Title_Requests')
PLATFORM_REPORTS_ATTRIBUTES = ("Data_Type",
"Access_Method")
PLATFORM_REPORT_FIELDS = ({NAME_KEY: 'platform',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('PR', 'PR_P1')},
{NAME_KEY: 'data_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('PR',)},
{NAME_KEY: 'access_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('PR',)})
# endregion
# region title report definitions
TITLE_REPORTS = ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')
TITLE_REPORTS_METRIC = ('Total_Item_Investigations',
'Total_Item_Requests',
'Unique_Item_Investigations',
'Unique_Item_Requests',
'Unique_Title_Investigations',
'Unique_Title_Requests',
'Limit_Exceeded',
'No_License')
TITLE_REPORTS_ATTRIBUTES = ("Data_Type",
"Section_Type",
"Access_Type",
"Access_Method",
"YOP")
TITLE_REPORT_FIELDS = ({NAME_KEY: 'title',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'publisher',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'publisher_id',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'platform',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'doi',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'proprietary_id',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'isbn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3')},
{NAME_KEY: 'print_issn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'online_issn',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'uri',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J1', 'TR_J2', 'TR_J3', 'TR_J4')},
{NAME_KEY: 'data_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR',)},
{NAME_KEY: 'section_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR',)},
{NAME_KEY: 'yop',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B1', 'TR_B2', 'TR_B3', 'TR_J4')},
{NAME_KEY: 'access_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR', 'TR_B3', 'TR_J3')},
{NAME_KEY: 'access_method',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',),
REPORTS_KEY: ('TR',)})
# endregion
# region fields that all reports have
ALL_REPORT_FIELDS = ({NAME_KEY: 'metric_type',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL', 'CHECK(metric_type <> \"\")')},
{NAME_KEY: 'vendor',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL', 'CHECK(vendor <> \"\")')},
{NAME_KEY: 'year',
TYPE_KEY: 'INTEGER',
OPTIONS_KEY: ('NOT NULL', 'CHECK(LENGTH(year) = 4)')},
{NAME_KEY: 'month',
TYPE_KEY: 'INTEGER',
OPTIONS_KEY: ('NOT NULL', 'CHECK(month BETWEEN 1 AND 12)')},
{NAME_KEY: 'metric',
TYPE_KEY: 'INTEGER',
OPTIONS_KEY: ('NOT NULL', 'CHECK(metric > 0)')},
{NAME_KEY: 'updated_on',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',)},
{NAME_KEY: 'file',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL',)})
# endregion
# region cost table fields
COST_FIELDS = ({NAME_KEY: 'cost_in_original_currency',
TYPE_KEY: 'REAL',
OPTIONS_KEY: ('NOT NULL', 'CHECK(cost_in_original_currency >= 0)')},
{NAME_KEY: 'original_currency',
TYPE_KEY: 'TEXT',
OPTIONS_KEY: ('NOT NULL', 'CHECK(original_currency <> \"\")')},
{NAME_KEY: 'cost_in_local_currency',
TYPE_KEY: 'REAL',
OPTIONS_KEY: ('NOT NULL', 'CHECK(cost_in_local_currency >= 0)')},
{NAME_KEY: 'cost_in_local_currency_with_tax',
TYPE_KEY: 'REAL',
OPTIONS_KEY: ('NOT NULL', 'CHECK(cost_in_local_currency_with_tax >= 0)')})
# endregion
# endregion
ALL_REPORTS = DATABASE_REPORTS + ITEM_REPORTS + PLATFORM_REPORTS + TITLE_REPORTS
REPORT_TYPE_SWITCHER = {'DR': {REPORTS_KEY: DATABASE_REPORTS, 'report_fields': DATABASE_REPORT_FIELDS},
'IR': {REPORTS_KEY: ITEM_REPORTS, 'report_fields': ITEM_REPORT_FIELDS},
'PR': {REPORTS_KEY: PLATFORM_REPORTS, 'report_fields': PLATFORM_REPORT_FIELDS},
'TR': {REPORTS_KEY: TITLE_REPORTS, 'report_fields': TITLE_REPORT_FIELDS}}
NAME_FIELD_SWITCHER = {'DR': 'database', 'IR': 'item', 'PR': 'platform', 'TR': 'title'}
MONTHS = {1: 'january', 2: 'february', 3: 'march', 4: 'april', 5: 'may', 6: 'june',
7: 'july', 8: 'august', 9: 'september', 10: 'october', 11: 'november', 12: 'december'}
MONTH_CALCULATION = 'COALESCE(SUM(CASE ' + 'month' + ' WHEN {} THEN ' + 'metric' + ' END), 0)'
YEAR_TOTAL = 'reporting_period_total'
YEAR_TOTAL_CALCULATION = 'SUM(' + 'metric' + ')'
RANKING = 'ranking'
RANKING_CALCULATION = 'RANK() OVER(ORDER BY ' + 'SUM(' + 'metric' + ')' + ' DESC)'
VIEW_SUFFIX = '_view'
COST_TABLE_SUFFIX = '_costs'
FIELDS_NOT_IN_VIEWS = ('month', 'metric', 'updated_on')
FIELDS_NOT_IN_KEYS = ('metric', 'updated_on')
FIELDS_NOT_IN_SEARCH_DROPDOWN = ('year',)
FIELDS_NOT_IN_CHARTS = FIELDS_NOT_IN_VIEWS + ('file',)
FIELDS_NOT_IN_TOP_NUMBER_CHARTS = FIELDS_NOT_IN_CHARTS + ('year',)
COSTS_KEY_FIELDS = ('vendor', 'year')
CHART_KEY_FIELDS = ('vendor', 'metric_type')
DATABASE_FOLDER = r'./all_data/search/'
DATABASE_LOCATION = DATABASE_FOLDER + r'search.db'
# All yearly reports tsv and json are saved here in original condition as backup
PROTECTED_DATABASE_FILE_DIR = "./all_data/.DO_NOT_MODIFY/"
FILE_SUBDIRECTORY_ORDER = ('year', 'vendor')
COSTS_SAVE_FOLDER = r'./all_data/costs/'
DELIMITERS = {'.tsv': '\t', '.csv': ','}
COMPARISON_OPERATORS = ('LIKE', 'NOT LIKE', '=', '<=', '<', '>=', '>', '<>')
NON_COMPARISONS = ('IS NULL', 'IS NOT NULL')
CURRENCY_LIST = ('USD', 'EUR', 'JPY', 'GBP', 'CHF', 'CAD', 'AUD')
# endregion
# region Variable Constants for FileDialog Filters
JSON_FILTER = ('JSON files (*.dat)',)
TSV_FILTER = ('TSV files (*.tsv)',)
CSV_FILTER = ('CSV files (*.csv)',)
EXCEL_FILTER = ('Excel files (*.xlsx)',)
# endregion
# region Variable Constants for FetchData
MONTH_NAMES = ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October",
"November", "December")
MASTER_REPORTS = ("DR", "IR", "PR", "TR")
class MajorReportType(Enum):
PLATFORM = "PR"
DATABASE = "DR"
TITLE = "TR"
ITEM = "IR"
class SpecialOptionType(Enum):
TO = 0 # Tabular Only, not included in request url, only used in creating tabular report
AO = 1 # Attribute Only, only in attributes_to_include, does not have it's own parameters in request url
AP = 2 # Attribute Parameter, in attributes_to_include and has it's own parameters in request url
ADP = 3 # Attribute Date Parameter, in attributes_to_include and has it's own date parameters in request url
POS = 4 # Parameter Only String, NOT in attributes_to_include and has it's own parameters in request url
POB = 5 # Parameter Only Bool, NOT in attributes_to_include and has it's own parameters in request url
SPECIAL_REPORT_OPTIONS = {
MajorReportType.PLATFORM: [(SpecialOptionType.AP, "Data_Type", ["Article",
"Book",
"Book_Segment",
"Database",
"Dataset",
"Journal",
"Multimedia",
"Newspaper_or_Newsletter",
"Other",
"Platform",
"Report",
"Repository_Item",
"Thesis_or_Dissertation"]),
(SpecialOptionType.AP, "Access_Method", ["Regular",
"TDM"]),
(SpecialOptionType.POS, "Metric_Type", ["Searches_Platform",
"Total_Item_Investigations",
"Total_Item_Requests",
"Unique_Item_Investigations",
"Unique_Item_Requests",
"Unique_Title_Investigations",
"Unique_Title_Requests"]),
(SpecialOptionType.TO, "Exclude_Monthly_Details")],
MajorReportType.DATABASE: [(SpecialOptionType.AP, "Data_Type", ["Book",
"Database",
"Journal",
"Multimedia",
"Newspaper_or_Newsletter",
"Other",
"Report",
"Repository_Item",
"Thesis_or_Dissertation"]),
(SpecialOptionType.AP, "Access_Method", ["Regular",
"TDM"]),
(SpecialOptionType.POS, "Metric_Type", ["Searches_Automated",
"Searches_Federated",
"Searches_Regular",
"Total_Item_Investigations",
"Total_Item_Requests",
"Unique_Item_Investigations",
"Unique_Item_Requests",
"Unique_Title_Investigations",
"Unique_Title_Requests",
"Limit_Exceeded",
"No_License"]),
(SpecialOptionType.TO, "Exclude_Monthly_Details")],
MajorReportType.TITLE: [(SpecialOptionType.AP, "Data_Type", ["Book",
"Journal",
"Newspaper_or_Newsletter",
"Other",
"Report",
"Thesis_or_Dissertation"]),
(SpecialOptionType.AP, "Section_Type", ["Article",
"Book",
"Chapter",
"Other",
"Section"]),
(SpecialOptionType.AP, "Access_Type", ["Controlled",
"OA_Gold"]),
(SpecialOptionType.AP, "Access_Method", ["Regular",
"TDM"]),
(SpecialOptionType.POS, "Metric_Type", ["Total_Item_Investigations",
"Total_Item_Requests",
"Unique_Item_Investigations",
"Unique_Item_Requests",
"Unique_Title_Investigations",
"Unique_Title_Requests",
"Limit_Exceeded",
"No_License"]),
(SpecialOptionType.ADP, "YOP"),
(SpecialOptionType.TO, "Exclude_Monthly_Details")],
MajorReportType.ITEM: [(SpecialOptionType.AP, "Data_Type", ["Article",
"Book",
"Book_Segment",
"Dataset",
"Journal",
"Multimedia",
"Newspaper_or_Newsletter",
"Other",
"Report",
"Repository_Item",
"Thesis_or_Dissertation"]),
(SpecialOptionType.AP, "Access_Type", ["Controlled",
"OA_Gold",
"Other_Free_To_Read"]),
(SpecialOptionType.AP, "Access_Method", ["Regular",
"TDM"]),
(SpecialOptionType.POS, "Metric_Type", ["Total_Item_Investigations",
"Total_Item_Requests",
"Unique_Item_Investigations",
"Unique_Item_Requests",
"Limit_Exceeded",
"No_License"]),
(SpecialOptionType.ADP, "YOP"),
(SpecialOptionType.AO, "Authors"),
(SpecialOptionType.AO, "Publication_Date"),
(SpecialOptionType.AO, "Article_Version"),
(SpecialOptionType.POB, "Include_Component_Details"),
(SpecialOptionType.POB, "Include_Parent_Details"),
(SpecialOptionType.TO, "Exclude_Monthly_Details")]
}
DEFAULT_SPECIAL_OPTION_VALUE = "all"
# If these codes are received with a Report_Header, files will be created and saved
ACCEPTABLE_CODES = [3030,
3031,
3032,
3040,
3050,
3060,
3062] + list(range(1, 1000))
# If these codes are received the retry checkbox will be checked, user can retry later
RETRY_LATER_CODES = [1010,
1011]
RETRY_WAIT_TIME = 5 # Seconds
class CompletionStatus(Enum):
SUCCESSFUL = "Successful!"
WARNING = "Warning!"
FAILED = "Failed!"
CANCELLED = "Cancelled!"
# endregion
# region Variable Constants for Settings
SETTINGS_FILE_DIR = "./all_data/settings/"
SETTINGS_FILE_NAME = "settings.dat"
# Default Settings
SHOW_DEBUG_MESSAGES = False
YEARLY_DIR = "./all_data/yearly_files/"
OTHER_DIR = "./all_data/other_files/"
REQUEST_INTERVAL = 3 # Seconds
REQUEST_TIMEOUT = 120 # Seconds
CONCURRENT_VENDORS = 2
CONCURRENT_REPORTS = 2
USER_AGENT = "Mozilla/5.0 Firefox/73.0 Chrome/80.0.3987.132 Safari/605.1.15"
DEFAULT_CURRENCY = 'USD'
# endregion
# region Variable Constants for ManageVendors
VENDORS_FILE_DIR = "./all_data/vendor_manager/"
VENDORS_FILE_NAME = "vendors.dat"
VENDORS_FILE_PATH = VENDORS_FILE_DIR + VENDORS_FILE_NAME
EXPORT_VENDORS_FILE_NAME = "exported_vendor_data.tsv"
# endregion

293
Costs.py

@ -0,0 +1,293 @@
import json
from PyQt5.QtWidgets import QDialog
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QFont
import ManageDB
import ManageVendors
from Settings import SettingsModel
from ui import CostsTab, ReportTypeDialog
from Constants import *
from GeneralUtils import *
class CostsController:
"""Controls the Costs tab
:param costs_ui: the UI for the costs_widget
:param settings: the user's settings"""
def __init__(self, costs_ui: CostsTab.Ui_costs_tab, settings: SettingsModel):
self.costs_ui = costs_ui
self.settings = settings
# set parameters
self.report_parameter_combobox = costs_ui.costs_report_parameter_combobox
self.report_parameter_combobox.addItems(REPORT_TYPE_SWITCHER.keys())
self.report_parameter = None
self.vendor_parameter_combobox = costs_ui.costs_vendor_parameter_combobox
self.vendor_parameter = None
self.year_parameter_dateedit = costs_ui.costs_year_parameter_dateedit
self.year_parameter_dateedit.setDate(QDate.currentDate())
self.year_parameter = None
self.name_label = costs_ui.costs_name_parameter_label
self.name_parameter_combobox = costs_ui.costs_name_parameter_combobox
self.name_parameter = None
# set up values
self.cost_in_original_currency_doublespinbox = costs_ui.costs_cost_in_original_currency_doublespinbox
self.cost_in_original_currency = 0.0
self.original_currency_combobox = costs_ui.costs_original_currency_value_combobox
self.load_currency_list()
self.original_currency = ''
self.cost_in_local_currency_doublespinbox = costs_ui.costs_cost_in_local_currency_doublespinbox
self.cost_in_local_currency = 0.0
self.cost_in_local_currency_with_tax_doublespinbox = \
costs_ui.costs_cost_in_local_currency_with_tax_doublespinbox
self.cost_in_local_currency_with_tax = 0.0
# set up buttons
self.save_costs_button = costs_ui.costs_save_button
self.save_costs_button.clicked.connect(self.save_costs)
self.load_button = costs_ui.costs_load_button
self.load_button.clicked.connect(self.load_costs)
self.clear_button = costs_ui.costs_clear_button
self.clear_button.clicked.connect(self.clear_costs)
vendors_json_string = read_json_file(ManageVendors.VENDORS_FILE_PATH)
vendor_dicts = json.loads(vendors_json_string)
self.vendor_parameter_combobox.clear()
self.vendor_parameter_combobox.addItems([vendor_dict[NAME_KEY] for vendor_dict in vendor_dicts])
self.report_parameter_combobox.currentTextChanged.connect(self.on_report_parameter_changed)
self.vendor_parameter_combobox.currentTextChanged.connect(self.on_vendor_parameter_changed)
self.year_parameter_dateedit.dateChanged.connect(self.on_year_parameter_changed)
self.name_parameter_combobox.currentTextChanged.connect(self.on_name_parameter_changed)
self.names = []
self.costs_names = []
self.on_report_parameter_changed()
self.year_parameter = int(self.year_parameter_dateedit.text())
self.vendor_parameter = self.vendor_parameter_combobox.currentText()
self.fill_names()
self.cost_in_original_currency_doublespinbox.valueChanged.connect(self.on_cost_in_original_currency_changed)
self.original_currency_combobox.currentTextChanged.connect(self.on_original_currency_changed)
self.cost_in_local_currency_doublespinbox.valueChanged.connect(self.on_cost_in_local_currency_changed)
self.cost_in_local_currency_with_tax_doublespinbox.valueChanged.connect(
self.on_cost_in_local_currency_with_tax_changed)
self.import_costs_button = costs_ui.costs_import_costs_button
self.import_costs_button.clicked.connect(self.import_costs)
def update_settings(self, settings: SettingsModel):
"""Invoked when the settings are saved
:param settings: the new settings"""
self.settings = settings
self.load_currency_list()
def database_updated(self, code: int):
"""Invoked when the database is updated
:param code: the exit code of the update"""
self.fill_names()
def load_vendor_list(self, vendors: Sequence[ManageVendors.Vendor]):
"""Updates the vendor list combobox
:param vendors: the new list of vendors"""
self.vendor_parameter_combobox.clear()
self.vendor_parameter_combobox.addItems([vendor.name for vendor in vendors])
def load_currency_list(self):
"""Updates the original currency combobox"""
self.original_currency_combobox.clear()
self.original_currency_combobox.addItem(self.settings.default_currency)
self.original_currency_combobox.addItems([currency for currency in CURRENCY_LIST if currency !=
self.settings.default_currency])
self.original_currency_combobox.setCurrentText('')
def on_report_parameter_changed(self):
"""Invoked when the report parameter changes"""
self.report_parameter = self.report_parameter_combobox.currentText()
self.name_label.setText(NAME_FIELD_SWITCHER[self.report_parameter].capitalize())
if self.vendor_parameter:
self.fill_names()
def on_vendor_parameter_changed(self):
"""Invoked when the vendor parameter changes"""
self.vendor_parameter = self.vendor_parameter_combobox.currentText()
if self.report_parameter:
self.fill_names()
def on_year_parameter_changed(self):
"""Invoked when the year parameter changes"""
self.year_parameter = int(self.year_parameter_dateedit.text())
self.load_costs()
self.fill_names(True)
def fill_names(self, only_get_costs_names: bool = False):
"""Fills the name field combobox"""
self.name_parameter_combobox.clear()
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
if not only_get_costs_names:
names_sql_text, names_data = ManageDB.get_names_sql_text(self.report_parameter, self.vendor_parameter)
names_results = ManageDB.run_select_sql(connection, names_sql_text, names_data)
if names_results:
self.names = [result[0] for result in names_results]
else:
self.names = []
if self.settings.show_debug_messages: print(names_results)
costs_sql_text, costs_data = ManageDB.get_names_with_costs_sql_text(self.report_parameter,
self.vendor_parameter,
self.year_parameter,
self.year_parameter)
costs_results = ManageDB.run_select_sql(connection, costs_sql_text, costs_data)
connection.close()
if costs_results:
self.costs_names = [result[0] for result in costs_results]
else:
self.costs_names = []
if self.settings.show_debug_messages: print(costs_results)
model = QStandardItemModel()
for name in self.names:
item = QStandardItem(name)
if name in self.costs_names:
font = QFont()
font.setBold(True)
item.setFont(font)
model.appendRow(item)
self.name_parameter_combobox.setModel(model)
else:
print('Error, no connection')
def on_name_parameter_changed(self):
"""Invoked when the name field parameter changes"""
self.name_parameter = self.name_parameter_combobox.currentText()
enable = False
if self.name_parameter:
enable = True
self.load_costs()
self.cost_in_original_currency_doublespinbox.setEnabled(enable)
self.original_currency_combobox.setEnabled(enable)
self.cost_in_local_currency_doublespinbox.setEnabled(enable)
self.cost_in_local_currency_with_tax_doublespinbox.setEnabled(enable)
def on_cost_in_original_currency_changed(self):
"""Invoked when the cost in original currency parameter changes"""
self.cost_in_original_currency = self.cost_in_original_currency_doublespinbox.value()
def on_original_currency_changed(self):
"""Invoked when the original currency parameter changes"""
self.original_currency = self.original_currency_combobox.currentText()
def on_cost_in_local_currency_changed(self):
"""Invoked when the cost in local currency parameter changes"""
self.cost_in_local_currency = self.cost_in_local_currency_doublespinbox.value()
def on_cost_in_local_currency_with_tax_changed(self):
"""Invoked when the cost in local currency with tax parameter changes"""
self.cost_in_local_currency_with_tax = self.cost_in_local_currency_with_tax_doublespinbox.value()
def save_costs(self):
"""Saves the cost data: if it is nonzero, add it to the database; if it is zero, delete it from the database"""
INSERT = 'insert'
DELETE = 'delete'
insert_or_delete = None
sql_text = None
data = None
if self.cost_in_original_currency > 0 and self.original_currency != '' \
and self.cost_in_local_currency > 0 and self.cost_in_local_currency_with_tax > 0:
insert_or_delete = INSERT
elif self.cost_in_original_currency == 0 and self.original_currency == '' \
and self.cost_in_local_currency == 0 and self.cost_in_local_currency_with_tax == 0:
insert_or_delete = DELETE
if insert_or_delete == INSERT:
sql_text, data = ManageDB.replace_costs_sql_text(self.report_parameter,
({NAME_FIELD_SWITCHER[self.report_parameter]:
self.name_parameter,
'vendor': self.vendor_parameter,
'year': self.year_parameter,
'cost_in_original_currency':
self.cost_in_original_currency,
'original_currency': self.original_currency,
'cost_in_local_currency': self.cost_in_local_currency,
'cost_in_local_currency_with_tax':
self.cost_in_local_currency_with_tax},))
elif insert_or_delete == DELETE:
sql_text, data = ManageDB.delete_costs_sql_text(self.report_parameter, self.vendor_parameter,
self.year_parameter, self.name_parameter)
if insert_or_delete in (INSERT, DELETE):
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
ManageDB.run_sql(connection, sql_text, data)
connection.close()
ManageDB.backup_costs_data(self.report_parameter)
if insert_or_delete == INSERT:
show_message('Data inserted/replaced')
elif insert_or_delete == DELETE:
show_message('Data removed')
else:
show_message('Invalid entry')
def load_costs(self):
"""Fills the costs fields with data from the database"""
sql_text, data = ManageDB.get_costs_sql_text(self.report_parameter, self.vendor_parameter, self.year_parameter,
self.name_parameter)
results = []
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
results = ManageDB.run_select_sql(connection, sql_text, data)
if not results:
results.append((0.0, '', 0.0, 0.0))
connection.close()
values = {}
index = 0
for field in COST_FIELDS:
values[field[NAME_KEY]] = results[0][index]
index += 1
self.cost_in_original_currency_doublespinbox.setValue(values['cost_in_original_currency'])
self.original_currency_combobox.setCurrentText(values['original_currency'])
self.cost_in_local_currency_doublespinbox.setValue(values['cost_in_local_currency'])
self.cost_in_local_currency_with_tax_doublespinbox.setValue(values['cost_in_local_currency_with_tax'])
self.cost_in_original_currency_doublespinbox.repaint()
def clear_costs(self):
"""Empties the costs fields"""
self.cost_in_original_currency_doublespinbox.setValue(0.0)
self.original_currency_combobox.setCurrentText('')
self.cost_in_local_currency_doublespinbox.setValue(0.0)
self.cost_in_local_currency_with_tax_doublespinbox.setValue(0.0)
def import_costs(self):
"""Import a file with costs data in it into the database"""
report_type_dialog = QDialog()
report_type_dialog_ui = ReportTypeDialog.Ui_report_type_dialog()
report_type_dialog_ui.setupUi(report_type_dialog)
report_type_dialog_ui.report_type_combobox.addItems(REPORT_TYPE_SWITCHER.keys())
report_type_dialog.show()
if report_type_dialog.exec_():
report_type = report_type_dialog_ui.report_type_combobox.currentText()
if report_type != '':
file_name = choose_file(TSV_FILTER + CSV_FILTER)
if file_name != '':
ManageDB.insert_single_cost_file(report_type, file_name)
ManageDB.backup_costs_data(report_type)
show_message('File ' + file_name + ' imported')
else:
print('Error, no file location selected')
else:
print('Error, no report type selected')

25
DataStorage.py

@ -0,0 +1,25 @@
import os
def save_json_file(file_dir: str, file_name: str, json_string: str):
try:
if not os.path.isdir(file_dir):
os.makedirs(file_dir)
file = open(file_dir + file_name, 'w')
file.write(json_string)
file.close()
except IOError as e:
print(e)
def read_json_file(file_path: str):
json_string = "[]"
try:
file = open(file_path, 'r')
json_string = file.read()
file.close()
except IOError as e:
print(e)
finally:
return json_string

3067
FetchData.py

File diff suppressed because it is too large Load Diff

140
GeneralUtils.py

@ -0,0 +1,140 @@
import webbrowser
import shlex
import subprocess
import platform
import csv
from typing import Sequence, Any
from os import path, makedirs, system
from PyQt5.QtWidgets import QWidget, QMessageBox, QFileDialog
from PyQt5.QtCore import QDate
main_window: QWidget = None
class JsonModel:
def from_json(self, json_dict: dict):
raise NotImplementedError("from_json method is not implemented")
def save_json_file(file_dir: str, file_name: str, json_string: str):
try:
if not path.isdir(file_dir):
makedirs(file_dir)
file = open(file_dir + file_name, 'w')
file.write(json_string)
file.close()
except IOError as e:
print(e)
def read_json_file(file_path: str) -> str:
json_string = "[]"
try:
file = open(file_path, 'r', encoding='utf-8-sig')
json_string = file.read()
file.close()
except IOError:
pass
finally:
return json_string
def show_message(message: str):
message_box = QMessageBox(main_window)
message_box.setMinimumSize(800, 800)
message_box.setWindowTitle("Info")
message_box.setText(message)
message_box.exec_()
def ask_confirmation(message: str = 'Are you sure you want to continue?') -> bool:
reply = QMessageBox.question(main_window, "Confirm", message, QMessageBox.Yes, QMessageBox.No)
return reply == QMessageBox.Yes
def open_file_or_dir(target_path: str):
if path.exists(target_path):
if platform.system() == "Darwin":
system("open " + shlex.quote(target_path))
elif platform.system() == "Linux":
subprocess.call(["xdg-open", target_path])
else:
webbrowser.open_new_tab(path.realpath(target_path))
else:
show_message(f"\'{target_path}\' does not exist")
def choose_file(name_filters) -> str:
file_path = ""
dialog = QFileDialog(main_window, directory=".")
dialog.setFileMode(QFileDialog.ExistingFile)
dialog.setNameFilters(name_filters)
if dialog.exec_():
file_path = dialog.selectedFiles()[0]
return file_path
def choose_directory() -> str:
dir_path = ""
dialog = QFileDialog(main_window, directory=".")
dialog.setFileMode(QFileDialog.Directory)
if dialog.exec_():
dir_path = dialog.selectedFiles()[0] + "/"
return dir_path
def choose_save(name_filters) -> str:
file_path = ""
dialog = QFileDialog(main_window, directory=".")
dialog.setFileMode(QFileDialog.AnyFile)
dialog.setAcceptMode(QFileDialog.AcceptSave)
dialog.setNameFilters(name_filters)
if dialog.exec_():
file_path = dialog.selectedFiles()[0]
return file_path
def open_in_browser(url: str):
webbrowser.open_new_tab(url)
def get_yearly_file_dir(base_path: str, vendor_name: str, begin_date: QDate) -> str:
return f"{base_path}{begin_date.toString('yyyy')}/{vendor_name}/"
def get_yearly_file_name(vendor_name: str, report_type: str, begin_date: QDate) -> str:
return f"{begin_date.toString('yyyy')}_{vendor_name}_{report_type}.tsv"
def get_special_file_dir(base_path: str, vendor_name: str) -> str:
return f"{base_path}{vendor_name}/special/"
def get_special_file_name(vendor_name: str, report_type: str, begin_date: QDate, end_date: QDate) -> str:
return f"{vendor_name}_{report_type}_{begin_date.toString('yyyy-MMM')}_{end_date.toString('yyyy-MMM')}_S.tsv"
def get_other_file_dir(base_path: str, vendor_name: str) -> str:
return f"{base_path}{vendor_name}/"
def get_other_file_name(vendor_name: str, report_type: str, begin_date: QDate, end_date: QDate) -> str:
return f"{vendor_name}_{report_type}_{begin_date.toString('yyyy-MMM')}_{end_date.toString('yyyy-MMM')}.tsv"
def save_data_as_tsv(file_name: str, data: Sequence[Any]):
"""Saves data in a TSV file
:param file_name: the name and location to save the results at
:param data: the data to save in the file"""
file = open(file_name, 'w', newline="", encoding='utf-8-sig')
if file.mode == 'w':
output = csv.writer(file, delimiter='\t', quotechar='\"')
for row in data:
output.writerow(row)
file.close()
else:
print('Error: could not open file ' + file_name)

284
ImportFile.py

@ -0,0 +1,284 @@
"""This module handles all operations involving importing reports."""
import shutil
import platform
import ctypes
import csv
from os import path, makedirs
from PyQt5.QtCore import QModelIndex, QDate, Qt
from PyQt5.QtWidgets import QWidget, QDialog, QDialogButtonBox
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5 import QtWidgets
import GeneralUtils
from Constants import *
from ui import ImportReportTab, ReportResultWidget
from ManageVendors import Vendor
from FetchData import ALL_REPORTS, CompletionStatus
from Settings import SettingsModel
from ManageDB import UpdateDatabaseWorker
class ProcessResult:
"""This holds the results of an import process
:param vendor: The target vendor
:param report_type: The target report type
"""
def __init__(self, vendor: Vendor, report_type: str):
self.vendor = vendor
self.report_type = report_type
self.completion_status = CompletionStatus.SUCCESSFUL
self.message = ""
self.file_name = ""
self.file_dir = ""
self.file_path = ""
class ImportReportController:
"""Controls the Import Report tab
:param vendors: The list of vendors in the system
:param settings: The user's settings
:param import_report_widget: The import report widget.
:param import_report_ui: The UI for the import_report_widget.
"""
def __init__(self, vendors: list, settings: SettingsModel, import_report_widget: QWidget,
import_report_ui: ImportReportTab.Ui_import_report_tab):
# region General
self.import_report_widget = import_report_widget
self.vendors = vendors
self.date = QDate.currentDate()
self.selected_vendor_index = -1
self.selected_report_type_index = -1
self.selected_file_path: str = ""
self.settings = settings
self.result_dialog = None
# endregion
# region Vendors
self.vendor_list_view = import_report_ui.vendors_list_view_import
self.vendor_list_model = QStandardItemModel(self.vendor_list_view)
self.vendor_list_view.setModel(self.vendor_list_model)
self.vendor_list_view.clicked.connect(self.on_vendor_selected)
self.update_vendors_ui()
# endregion
# region Report Types
self.report_type_list_view = import_report_ui.report_types_list_view_import
self.report_type_list_model = QStandardItemModel(self.report_type_list_view)
self.report_type_list_view.setModel(self.report_type_list_model)
self.report_type_list_view.clicked.connect(self.on_report_type_selected)
for report_type in ALL_REPORTS:
item = QStandardItem(report_type)
item.setEditable(False)
self.report_type_list_model.appendRow(item)
# endregion
# region Others
self.year_date_edit = import_report_ui.report_year_date_edit
self.year_date_edit.setDate(self.date)
self.year_date_edit.dateChanged.connect(self.on_date_changed)
self.select_file_btn = import_report_ui.select_file_button
self.select_file_btn.clicked.connect(self.on_select_file_clicked)
self.selected_file_edit = import_report_ui.selected_file_edit
self.import_report_button = import_report_ui.import_report_button
self.import_report_button.clicked.connect(self.on_import_clicked)
# endregion
def on_vendors_changed(self, vendors: list):
"""Handles the signal emitted when the system's vendor list is updated
:param vendors: An updated list of the system's vendors
"""
self.selected_vendor_index = -1
self.update_vendors(vendors)
self.update_vendors_ui()
def update_vendors(self, vendors: list):
""" Updates the local copy of vendors that support report import
:param vendors: A list of vendors
"""
self.vendors = vendors
def update_vendors_ui(self):
"""Updates the UI to show vendors that support report import"""
self.vendor_list_model.clear()
for vendor in self.vendors:
item = QStandardItem(vendor.name)
item.setEditable(False)
self.vendor_list_model.appendRow(item)
def on_vendor_selected(self, model_index: QModelIndex):
"""Handles the signal emitted when a vendor is selected"""
self.selected_vendor_index = model_index.row()
def on_report_type_selected(self, model_index: QModelIndex):
"""Handles the signal emitted when a report type is selected"""
self.selected_report_type_index = model_index.row()
def on_date_changed(self, date: QDate):
"""Handles the signal emitted when the target date is changed"""
self.date = date
def on_select_file_clicked(self):
"""Handles the signal emitted when the select file button is clicked"""
file_path = GeneralUtils.choose_file(TSV_FILTER + CSV_FILTER)
if file_path:
self.selected_file_path = file_path
self.selected_file_edit.setText(file_path)
def on_import_clicked(self):
"""Handles the signal emitted when the import button is clicked"""
if self.selected_vendor_index == -1:
GeneralUtils.show_message("Select a vendor")
return
elif self.selected_report_type_index == -1:
GeneralUtils.show_message("Select a report type")
return
elif self.selected_file_path == "":
GeneralUtils.show_message("Select a file")
return
vendor = self.vendors[self.selected_vendor_index]
report_type = ALL_REPORTS[self.selected_report_type_index]
process_result = self.import_report(vendor, report_type)
self.show_result(process_result)
def import_report(self, vendor: Vendor, report_type: str) -> ProcessResult:
""" Imports the selected file using the selected parameters
:param vendor: The target vendor
:param report_type: The target report type
:raises Exception: If anything goes wrong while importing the report
"""
process_result = ProcessResult(vendor, report_type)
try:
dest_file_dir = GeneralUtils.get_yearly_file_dir(self.settings.yearly_directory, vendor.name, self.date)
dest_file_name = GeneralUtils.get_yearly_file_name(vendor.name, report_type, self.date)
dest_file_path = f"{dest_file_dir}{dest_file_name}"
# Verify that dest_file_dir exists
if not path.isdir(dest_file_dir):
makedirs(dest_file_dir)
# Validate report header
delimiter = DELIMITERS[self.selected_file_path[-4:].lower()]
file = open(self.selected_file_path, 'r', encoding='utf-8-sig')
reader = csv.reader(file, delimiter=delimiter, quotechar='\"')
if file.mode == 'r':
header = {}
for row in range(HEADER_ROWS): # reads header row data
cells = next(reader)
if cells:
key = cells[0].lower()
if key != HEADER_ENTRIES[row]:
raise Exception('File has invalid header (missing row ' + HEADER_ENTRIES[row] + ')')
else:
header[key] = cells[1].strip()
else:
raise Exception('File has invalid header (missing row ' + HEADER_ENTRIES[row] + ')')
for row in range(BLANK_ROWS):
cells = next(reader)
if cells:
if cells[0].strip():
raise Exception('File has invalid header (not enough blank rows)')
if header['report_id'] != report_type:
raise Exception('File has invalid header (wrong Report_Id)')
if not header['created']:
raise Exception('File has invalid header (no Created date)')
else:
raise Exception('Could not open file')
# Copy selected_file_path to dest_file_path
self.copy_file(self.selected_file_path, dest_file_path)
process_result.file_dir = dest_file_dir
process_result.file_name = dest_file_name
process_result.file_path = dest_file_path
process_result.completion_status = CompletionStatus.SUCCESSFUL
# Save protected tsv file
protected_file_dir = f"{PROTECTED_DATABASE_FILE_DIR}{self.date.toString('yyyy')}/{vendor.name}/"
if not path.isdir(protected_file_dir):
makedirs(protected_file_dir)
if platform.system() == "Windows":
ctypes.windll.kernel32.SetFileAttributesW(PROTECTED_DATABASE_FILE_DIR, 2) # Hide folder
protected_file_path = f"{protected_file_dir}{dest_file_name}"
self.copy_file(self.selected_file_path, protected_file_path)
# Add file to database
database_worker = UpdateDatabaseWorker([{'file': protected_file_path,
'vendor': vendor.name,
'year': int(self.date.toString('yyyy'))}],
False)
database_worker.work()
except Exception as e:
process_result.message = f"Exception: {e}"
process_result.completion_status = CompletionStatus.FAILED
return process_result
def copy_file(self, origin_path: str, dest_path: str):
"""Copies a file from origin_path to dest_path"""
shutil.copy2(origin_path, dest_path)
def show_result(self, process_result: ProcessResult):
"""Shows the result of the import process to the user
:param process_result: The result of the import process
"""
self.result_dialog = QDialog(self.import_report_widget, flags=Qt.WindowCloseButtonHint)
self.result_dialog.setWindowTitle("Import Result")
vertical_layout = QtWidgets.QVBoxLayout(self.result_dialog)
vertical_layout.setContentsMargins(5, 5, 5, 5)
report_result_widget = QWidget(self.result_dialog)
report_result_ui = ReportResultWidget.Ui_ReportResultWidget()
report_result_ui.setupUi(report_result_widget)
button_box = QtWidgets.QDialogButtonBox(QDialogButtonBox.Ok, self.result_dialog)
button_box.setCenterButtons(True)
button_box.accepted.connect(self.result_dialog.accept)
vendor = process_result.vendor
report_type = process_result.report_type
report_result_ui.report_type_label.setText(f"{vendor.name} - {report_type}")
report_result_ui.success_label.setText(process_result.completion_status.value)
if process_result.completion_status == CompletionStatus.SUCCESSFUL:
report_result_ui.message_label.hide()
report_result_ui.retry_frame.hide()
report_result_ui.file_label.setText(f"Saved as: {process_result.file_name}")
report_result_ui.file_label.mousePressEvent = \
lambda event: GeneralUtils.open_file_or_dir(process_result.file_path)
report_result_ui.folder_button.clicked.connect(
lambda: GeneralUtils.open_file_or_dir(process_result.file_dir))
report_result_ui.success_label.setText("Successful!")
report_result_ui.retry_frame.hide()
elif process_result.completion_status == CompletionStatus.FAILED:
report_result_ui.file_frame.hide()
report_result_ui.retry_frame.hide()
report_result_ui.message_label.setText(process_result.message)
vertical_layout.addWidget(report_result_widget)
vertical_layout.addWidget(button_box)
self.result_dialog.show()

3
JsonUtils.py

@ -0,0 +1,3 @@
class JsonModel:
def from_json(self, json_dict: dict):
raise NotImplementedError("from_json method is not implemented")

144
MainDriver.py

@ -0,0 +1,144 @@
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QFrame, QHBoxLayout, QPushButton
from PyQt5.QtGui import QIcon, QPixmap
from ui import MainWindow, ManageVendorsTab, SettingsTab, FetchReportsTab, FetchSpecialReportsTab, ImportReportTab,\
SearchTab, VisualTab, CostsTab
from ManageVendors import ManageVendorsController
from FetchData import FetchReportsController, FetchSpecialReportsController
from ImportFile import ImportReportController
from Costs import CostsController
from Search import SearchController
from Settings import SettingsController, SettingsModel
from Visual import VisualController
import GeneralUtils
import ManageDB
from Constants import *
# region debug_stuff
def trap_exc_during_debug(*args):
# when app raises uncaught exception, print info
print(args)
# install exception hook: without this, uncaught exception would cause application to exit
sys.excepthook = trap_exc_during_debug
# endregion
if hasattr(Qt, 'AA_EnableHighDpiScaling'):
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyleSheet("QWidget {font-family: Segoe UI; font-size: 12pt;}")
main_window = QMainWindow()
main_window_ui = MainWindow.Ui_mainWindow()
main_window_ui.setupUi(main_window)
GeneralUtils.main_window = main_window
# region Setup Tab Controllers
settings_tab = QWidget(main_window)
settings_ui = SettingsTab.Ui_settings_tab()
settings_ui.setupUi(settings_tab)
settings_controller = SettingsController(settings_tab, settings_ui)
manage_vendors_tab = QWidget(main_window)
manage_vendors_ui = ManageVendorsTab.Ui_manage_vendors_tab()
manage_vendors_ui.setupUi(manage_vendors_tab)
manage_vendors_controller = ManageVendorsController(manage_vendors_tab, manage_vendors_ui, settings_controller.settings)
ManageDB.update_settings(settings_controller.settings)
ManageDB.first_time_setup()
fetch_reports_tab = QWidget(main_window)
fetch_reports_ui = FetchReportsTab.Ui_fetch_reports_tab()
fetch_reports_ui.setupUi(fetch_reports_tab)
fetch_reports_controller = FetchReportsController(manage_vendors_controller.vendors, settings_controller.settings,
fetch_reports_tab, fetch_reports_ui)
fetch_special_reports_tab = QWidget(main_window)
fetch_special_reports_ui = FetchSpecialReportsTab.Ui_fetch_special_reports_tab()
fetch_special_reports_ui.setupUi(fetch_special_reports_tab)
fetch_special_reports_controller = FetchSpecialReportsController(manage_vendors_controller.vendors,
settings_controller.settings,
fetch_special_reports_tab,
fetch_special_reports_ui)
costs_tab = QWidget(main_window)
costs_tab_ui = CostsTab.Ui_costs_tab()
costs_tab_ui.setupUi(costs_tab)
costs_controller = CostsController(costs_tab_ui, settings_controller.settings)
import_report_tab = QWidget(main_window)
import_report_ui = ImportReportTab.Ui_import_report_tab()
import_report_ui.setupUi(import_report_tab)
import_report_controller = ImportReportController(manage_vendors_controller.vendors, settings_controller.settings,
import_report_tab, import_report_ui)
search_tab = QWidget(main_window)
search_ui = SearchTab.Ui_search_tab()
search_ui.setupUi(search_tab)
search_controller = SearchController(search_ui, settings_controller.settings)
visual_tab = QWidget(main_window)
visual_ui = VisualTab.Ui_visual_tab()
visual_ui.setupUi(visual_tab)
visual_controller = VisualController(visual_ui, settings_controller.settings)
# # endregion
# region Connect Signals
manage_vendors_controller.vendors_changed_signal.connect(fetch_reports_controller.on_vendors_changed)
manage_vendors_controller.vendors_changed_signal.connect(fetch_special_reports_controller.on_vendors_changed)
manage_vendors_controller.vendors_changed_signal.connect(import_report_controller.on_vendors_changed)
manage_vendors_controller.vendors_changed_signal.connect(costs_controller.load_vendor_list)
manage_vendors_controller.vendors_changed_signal.connect(visual_controller.load_vendor_list)
settings_controller.settings_changed_signal.connect(ManageDB.update_settings)
settings_controller.settings_changed_signal.connect(search_controller.update_settings)
settings_controller.settings_changed_signal.connect(costs_controller.update_settings)
settings_controller.settings_changed_signal.connect(visual_controller.update_settings)
ManageDB.managedb_signal_handler.database_changed_signal.connect(costs_controller.database_updated)
ManageDB.managedb_signal_handler.database_changed_signal.connect(visual_controller.database_updated)
# endregion
# region Add tabs to main window
main_window_ui.tab_widget.addTab(manage_vendors_tab, manage_vendors_tab.windowIcon(), "Manage Vendors")
main_window_ui.tab_widget.addTab(fetch_reports_tab, fetch_reports_tab.windowIcon(), "Fetch Reports")
main_window_ui.tab_widget.addTab(fetch_special_reports_tab, fetch_special_reports_tab.windowIcon(),
"Fetch Special Reports")
main_window_ui.tab_widget.addTab(import_report_tab, import_report_tab.windowIcon(), "Import Report")
main_window_ui.tab_widget.addTab(costs_tab, costs_tab.windowIcon(), "Costs")
main_window_ui.tab_widget.addTab(search_tab, search_tab.windowIcon(), "Search")
main_window_ui.tab_widget.addTab(visual_tab, visual_tab.windowIcon(), "Visual")
main_window_ui.tab_widget.addTab(settings_tab, settings_tab.windowIcon(), "Settings")
main_window_ui.tab_widget.setCurrentIndex(1)
# endregion
# region Status Bar
status_bar = main_window_ui.statusbar
help_frame = QFrame(status_bar)
help_frame_layout = QHBoxLayout(help_frame)
help_frame_layout.setContentsMargins(-1, 2, -1, 5)
help_frame.setLayout(help_frame_layout)
help_button = QPushButton("Help", help_frame)
help_pixmap = QPixmap(":/ui/resources/help_icon.png")
help_button.setIcon(QIcon(help_pixmap))
help_button.clicked.connect(lambda: GeneralUtils.open_in_browser(HELP_SITE))
help_frame_layout.addWidget(help_button)
status_bar.addWidget(help_frame)
# endregion
main_window.show()
sys.exit(app.exec_())

1071
ManageDB.py

File diff suppressed because it is too large Load Diff

648
ManageVendors.py

@ -0,0 +1,648 @@
"""This module handles all operations involving managing vendors."""
import csv
import os
import json
import validators
from PyQt5.QtWidgets import QDialog, QLabel, QDialogButtonBox, QWidget
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtCore import Qt, QObject, QModelIndex, pyqtSignal
from ui import ManageVendorsTab, AddVendorDialog, RemoveVendorDialog
import ManageDB
import GeneralUtils
from GeneralUtils import JsonModel
from Constants import *
from Settings import SettingsModel
class Vendor(JsonModel):
"""This holds a vendor's information
:param name: The vendor's unique name (Mandatory)
:param base_url: The base URL for making sushi report calls (must end with '/reports', mandatory)
:param customer_id: The customer id used in sushi report calls
:param requestor_id: The requestor id id used in sushi report calls
:param api_key: The api key id used in sushi report calls
:param platform: The platform id used in sushi report calls
:param is_non_sushi: This indicates if this vendor is sushi compatible
:param description: A description of this vendor
:param companies: More information about the vendor
"""
def __init__(self, name: str, base_url: str, customer_id: str, requestor_id: str, api_key: str, platform: str,
is_non_sushi: bool, description: str, companies: str):
self.name = name
self.base_url = base_url
self.customer_id = customer_id
self.requestor_id = requestor_id
self.api_key = api_key
self.platform = platform
self.is_non_sushi = is_non_sushi
self.description = description
self.companies = companies
@classmethod
def from_json(cls, json_dict: dict):
"""This returns a vendor object using the parameters in a json dict
:param json_dict: A dict containing a vendor's details
:return: Vendor
"""
name = json_dict["name"] if "name" in json_dict else ""
customer_id = json_dict["customer_id"] if "customer_id" in json_dict else ""
base_url = json_dict["base_url"] if "base_url" in json_dict else ""
requestor_id = json_dict["requestor_id"] if "requestor_id" in json_dict else ""
api_key = json_dict["api_key"] if "api_key" in json_dict else ""
platform = json_dict["platform"] if "platform" in json_dict else ""
is_non_sushi = json_dict["is_non_sushi"] if "is_non_sushi" in json_dict else False
description = json_dict["description"] if "description" in json_dict else ""
companies = json_dict["companies"] if "companies" in json_dict else ""
return cls(name, base_url, customer_id, requestor_id, api_key, platform, is_non_sushi, description, companies)
class ManageVendorsController(QObject):
"""Controls the Manage Vendors tab
:param manage_vendors_widget: The manage vendors widget.
:param manage_vendors_ui: The UI for the manage_vendors_widget.
"""
vendors_changed_signal = pyqtSignal(list)
def __init__(self, manage_vendors_widget: QWidget, manage_vendors_ui: ManageVendorsTab.Ui_manage_vendors_tab,
settings: SettingsModel):
super().__init__()
self.manage_vendors_widget = manage_vendors_widget
self.selected_index = -1
self.edit_vendor_details_frame = manage_vendors_ui.edit_vendor_details_frame
self.edit_vendor_options_frame = manage_vendors_ui.edit_vendor_options_frame
self.name_line_edit = manage_vendors_ui.nameEdit
self.customer_id_line_edit = manage_vendors_ui.customerIdEdit
self.base_url_line_edit = manage_vendors_ui.baseUrlEdit
self.requestor_id_line_edit = manage_vendors_ui.requestorIdEdit
self.api_key_line_edit = manage_vendors_ui.apiKeyEdit
self.platform_line_edit = manage_vendors_ui.platformEdit
self.non_Sushi_check_box = manage_vendors_ui.non_Sushi_check_box
self.description_text_edit = manage_vendors_ui.descriptionEdit
self.companies_text_edit = manage_vendors_ui.companiesEdit
manage_vendors_ui.non_sushi_help_button.clicked.connect(
lambda: GeneralUtils.show_message("Vendors that don't provide SUSHI service can be added to the list for "
"use with Import Reports"))
self.name_validation_label = manage_vendors_ui.name_validation_label
self.name_validation_label.hide()
self.url_validation_label = manage_vendors_ui.url_validation_label
self.url_validation_label.hide()
self.save_vendor_changes_button = manage_vendors_ui.saveVendorChangesButton
self.undo_vendor_changes_button = manage_vendors_ui.undoVendorChangesButton
self.remove_vendor_button = manage_vendors_ui.removeVendorButton
self.add_vendor_button = manage_vendors_ui.addVendorButton
self.export_vendors_button = manage_vendors_ui.exportVendorsButton
self.import_vendors_button = manage_vendors_ui.importVendorsButton
self.save_vendor_changes_button.clicked.connect(self.modify_vendor)
self.undo_vendor_changes_button.clicked.connect(self.populate_edit_vendor_view)
self.remove_vendor_button.clicked.connect(self.on_remove_vendor_clicked)
self.add_vendor_button.clicked.connect(self.on_add_vendor_clicked)
self.export_vendors_button.clicked.connect(self.on_export_vendors_clicked)
self.import_vendors_button.clicked.connect(self.on_import_vendors_clicked)
self.vendor_list_view = manage_vendors_ui.vendorsListView
self.vendor_list_model = QStandardItemModel(self.vendor_list_view)
self.vendor_list_view.setModel(self.vendor_list_model)
self.vendor_list_view.clicked.connect(self.on_vendor_selected)
self.settings = settings
self.vendors = []
self.vendor_names = set() # Hash set for faster operations
vendors_json_string = GeneralUtils.read_json_file(VENDORS_FILE_PATH)
vendor_dicts = json.loads(vendors_json_string)
for json_dict in vendor_dicts:
vendor = Vendor.from_json(json_dict)
self.vendors.append(vendor)
self.vendor_names.add(vendor.name.lower())
self.update_vendors_ui()
def on_vendor_selected(self, model_index: QModelIndex):
"""Handles the signal emitted when a vendor is selected
:param model_index: An object containing the location of the vendor on the vendor list
"""
self.selected_index = model_index.row()
self.populate_edit_vendor_view()
def on_name_text_changed(self, new_name: str, original_name: str, validation_label: QLabel, validate: bool = True):
"""Handles the signal emitted when a vendor's name is changed
:param new_name: The new name entered in the text field
:param original_name: The vendor's original name
:param validation_label: The label to show validation messages
:param validate: This indicates whether the new_name should be validated
"""
if not validate:
validation_label.hide()
return
is_valid, message = self.validate_new_name(new_name, original_name)
if is_valid:
validation_label.hide()
else:
validation_label.show()
validation_label.setText(message)
def on_url_text_changed(self, url: str, validation_label: QLabel, validate: bool = True):
"""Handles the signal emitted when a vendor's URL is changed
:param url: The URL entered in the text field
:param validation_label: The label to show validation messages
:param validate: This indicates whether the url should be validated
"""
if not validate:
validation_label.hide()
return
is_valid, message = self.validate_url(url)
if is_valid:
validation_label.hide()
else:
validation_label.show()
validation_label.setText(message)
def validate_new_name(self, new_name: str, original_name: str = "") -> (bool, str):
"""Validates a new vendor name
:param new_name: The new name to be validated
:param original_name: The original name
:returns: (is_successful, message) A Tuple with the completion status and a message
"""
if not new_name:
return False, "Vendor name can't be empty"
elif new_name.lower() in self.vendor_names:
if original_name and original_name.lower() == new_name.lower():
return True, ""
else:
return False, "Duplicate vendor name"
else:
return True, ""
def validate_url(self, url: str) -> (bool, str):
"""Validates a new url
:param url: The URL to be validated
:returns: (is_successful, message) A Tuple with the completion status and a message
"""
if not validators.url(url):
return False, "Invalid Url"
elif not url.endswith("/reports"):
return False, "URL must end with '/reports'"
else:
return True, ""
def update_vendors_ui(self):
"""Updates the UI to show all vendors"""
self.vendor_list_model.clear()
for vendor in self.vendors:
item = QStandardItem(vendor.name)
item.setEditable(False)
self.vendor_list_model.appendRow(item)
self.populate_edit_vendor_view()
def update_vendor_names(self):
"""Updates the local set of vendor names used for validation"""
self.vendor_names.clear()
for vendor in self.vendors:
self.vendor_names.add(vendor.name.lower())
def add_vendor(self, new_vendor: Vendor) -> (bool, str):
"""Adds a new vendor to the system if the vendor is valid
:param new_vendor: The new vendor to be added
:returns: (is_successful, message) A Tuple with the completion status and a message
"""
# Check if vendor is valid
is_valid, message = self.validate_new_name(new_vendor.name)
if not is_valid:
return is_valid, message
if not new_vendor.is_non_sushi:
is_valid, message = self.validate_url(new_vendor.base_url)
if not is_valid:
return is_valid, message
self.vendors.append(new_vendor)
self.vendor_names.add(new_vendor.name.lower())
return True, ""
def modify_vendor(self):
"""Updates a vendor's information in the system if the vendor is valid"""
if self.selected_index < 0:
if self.settings.show_debug_messages: print("No vendor selected")
return
selected_vendor = self.vendors[self.selected_index]
# Check if entries are valid
new_name = self.name_line_edit.text()
original_name = selected_vendor.name
is_valid, message = self.validate_new_name(new_name, original_name)
if not is_valid:
GeneralUtils.show_message(message)
return
if not self.non_Sushi_check_box.isChecked():
url = self.base_url_line_edit.text()
is_valid, message = self.validate_url(url)
if not is_valid:
GeneralUtils.show_message(message)
return
# Apply Changes
if original_name != new_name:
self.update_name_of_file_and_folder(original_name, new_name)
ManageDB.update_vendor_in_all_tables(original_name, new_name)
for report_type in REPORT_TYPE_SWITCHER.keys():
ManageDB.backup_costs_data(report_type)
selected_vendor.name = self.name_line_edit.text()
selected_vendor.base_url = self.base_url_line_edit.text()
selected_vendor.customer_id = self.customer_id_line_edit.text()
selected_vendor.requestor_id = self.requestor_id_line_edit.text()
selected_vendor.api_key = self.api_key_line_edit.text()
selected_vendor.platform = self.platform_line_edit.text()
selected_vendor.is_non_sushi = self.non_Sushi_check_box.checkState() == Qt.Checked
selected_vendor.description = self.description_text_edit.toPlainText()
selected_vendor.companies = self.companies_text_edit.toPlainText()
self.update_vendors_ui()
self.update_vendor_names()
self.vendors_changed_signal.emit(self.vendors)
self.save_all_vendors_to_disk()
GeneralUtils.show_message("Changes Saved!")
def update_name_of_file_and_folder(self,original_name, new_name):
DO_NOT_MODIFY_json_path = os.getcwd() + os.path.sep + "all_data" + os.path.sep + ".DO_NOT_MODIFY" + os.path.sep + "_json"
DO_NOT_MODIFY_year_path = os.getcwd() + os.path.sep + "all_data" + os.path.sep + ".DO_NOT_MODIFY"
default_year_path = os.getcwd() + os.path.sep + "all_data" + os.path.sep + "yearly_files"
default_other_path = os.getcwd() + os.path.sep + "all_data" + os.path.sep + "other_files"
custom_year_path = self.settings.yearly_directory
custom_other_path = self.settings.other_directory
if os.path.exists(DO_NOT_MODIFY_json_path):
folderList = os.listdir(DO_NOT_MODIFY_json_path)
for folder in folderList:
if folder[0] == "2" and folder[1] == "0":
year_path = DO_NOT_MODIFY_json_path + os.path.sep + folder
original_folder_path = year_path + os.path.sep + original_name
new_folder_path = year_path + os.path.sep + new_name
if os.path.exists(original_folder_path):
filesList = os.listdir(original_folder_path)
for theFile in filesList:
old_file_path = original_folder_path + os.path.sep + theFile
new_file_path = original_folder_path + os.path.sep + theFile.replace(original_name,new_name)
os.rename(old_file_path,new_file_path)
os.rename(original_folder_path,new_folder_path)
if (os.path.exists(DO_NOT_MODIFY_year_path)):
folderList = os.listdir(DO_NOT_MODIFY_json_path)
for folder in folderList:
if folder[0] == "2" and folder[1] == "0":
year_path = DO_NOT_MODIFY_year_path + os.path.sep + folder
original_folder_path = year_path + os.path.sep + original_name
new_folder_path = year_path + os.path.sep + new_name
if os.path.exists(original_folder_path):
filesList = os.listdir(original_folder_path)
for theFile in filesList:
old_file_path = original_folder_path + os.path.sep + theFile
new_file_path = original_folder_path + os.path.sep + theFile.replace(original_name, new_name)
os.rename(old_file_path, new_file_path)
os.rename(original_folder_path, new_folder_path)
if (os.path.exists(default_year_path)):
folderList = os.listdir(DO_NOT_MODIFY_json_path)
for folder in folderList:
if folder[0] == "2" and folder[1] == "0":
year_path = default_year_path + os.path.sep + folder
original_folder_path = year_path + os.path.sep + original_name
new_folder_path = year_path + os.path.sep + new_name
if os.path.exists(original_folder_path):
filesList = os.listdir(original_folder_path)
for theFile in filesList:
old_file_path = original_folder_path + os.path.sep + theFile
new_file_path = original_folder_path + os.path.sep + theFile.replace(original_name, new_name)
os.rename(old_file_path, new_file_path)
os.rename(original_folder_path, new_folder_path)
if (os.path.exists(default_other_path)):
original_folder_path = default_other_path + os.path.sep + original_name
new_folder_path = default_other_path + os.path.sep + new_name
if os.path.exists(original_folder_path):
filesList = os.listdir(original_folder_path)
for theFile in filesList:
old_file_path = original_folder_path + os.path.sep + theFile
new_file_path = original_folder_path + os.path.sep + theFile.replace(original_name,
new_name)
os.rename(old_file_path, new_file_path)
os.rename(original_folder_path, new_folder_path)
if (os.path.exists(custom_year_path)):
folderList = os.listdir(custom_year_path)
for folder in folderList:
if folder[0] == "2" and folder[1] == "0":
year_path = custom_year_path + os.path.sep + folder
original_folder_path = year_path + os.path.sep + original_name
new_folder_path = year_path + os.path.sep + new_name
if os.path.exists(original_folder_path):
filesList = os.listdir(original_folder_path)
for theFile in filesList:
old_file_path = original_folder_path + os.path.sep + theFile
new_file_path = original_folder_path + os.path.sep + theFile.replace(original_name,
new_name)
os.rename(old_file_path, new_file_path)
os.rename(original_folder_path, new_folder_path)
if (os.path.exists(custom_other_path)):
original_folder_path = custom_other_path + os.path.sep + original_name
new_folder_path = custom_other_path + os.path.sep + new_name
if os.path.exists(original_folder_path):
filesList = os.listdir(original_folder_path)
for theFile in filesList:
old_file_path = original_folder_path + os.path.sep + theFile
new_file_path = original_folder_path + os.path.sep + theFile.replace(original_name,
new_name)
os.rename(old_file_path, new_file_path)
os.rename(original_folder_path, new_folder_path)
def on_add_vendor_clicked(self):
"""Handles the signal emitted when the add vendor button is clicked
A dialog is show to allow the user to enter a new vendor's information. If the information entered is valid,
the vendor is added to the system
"""
vendor_dialog = QDialog()
vendor_dialog_ui = AddVendorDialog.Ui_addVendorDialog()
vendor_dialog_ui.setupUi(vendor_dialog)
name_edit = vendor_dialog_ui.nameEdit
base_url_edit = vendor_dialog_ui.baseUrlEdit
customer_id_edit = vendor_dialog_ui.customerIdEdit
requestor_id_edit = vendor_dialog_ui.requestorIdEdit
api_key_edit = vendor_dialog_ui.apiKeyEdit
platform_edit = vendor_dialog_ui.platformEdit
non_sushi_check_box = vendor_dialog_ui.non_Sushi_check_box
description_edit = vendor_dialog_ui.descriptionEdit
companies_edit = vendor_dialog_ui.companiesEdit
vendor_dialog_ui.non_sushi_help_button.clicked.connect(
lambda: GeneralUtils.show_message("Vendors that don't provide SUSHI service can be added to the list for "
"use with Import Reports"))
name_validation_label = vendor_dialog_ui.name_validation_label
name_validation_label.hide()
url_validation_label = vendor_dialog_ui.url_validation_label
url_validation_label.hide()
name_edit.textChanged.connect(
lambda new_name: self.on_name_text_changed(new_name, "", name_validation_label))
base_url_edit.textChanged.connect(
lambda url: self.on_url_text_changed(url, url_validation_label))
def attempt_add_vendor():
vendor = Vendor(name_edit.text(), base_url_edit.text(), customer_id_edit.text(), requestor_id_edit.text(),
api_key_edit.text(), platform_edit.text(), non_sushi_check_box.checkState() == Qt.Checked,
description_edit.toPlainText(), companies_edit.toPlainText())
is_valid, message = self.add_vendor(vendor)
if is_valid:
self.sort_vendors()
self.selected_index = -1
self.update_vendors_ui()
self.populate_edit_vendor_view()
self.vendors_changed_signal.emit(self.vendors)
self.save_all_vendors_to_disk()
vendor_dialog.close()
else:
GeneralUtils.show_message(message)
button_box = vendor_dialog_ui.buttonBox
ok_button = button_box.button(QDialogButtonBox.Ok)
ok_button.clicked.connect(attempt_add_vendor)
cancel_button = button_box.button(QDialogButtonBox.Cancel)
cancel_button.clicked.connect(lambda: vendor_dialog.close())
vendor_dialog.exec_()
def on_import_vendors_clicked(self):
"""Handles the signal emitted when the import vendors button is clicked.
A file select dialog is shown to allow the user to select the vendors TSV file to import. The selected file is
then imported.
"""
file_path = GeneralUtils.choose_file(TSV_FILTER)
if file_path:
self.import_vendors_tsv(file_path)
def on_export_vendors_clicked(self):
"""Handles the signal emitted when the export vendors button is clicked.
A folder select dialog is shown to allow the user to select the target directory to export the vendors file to.
A vendors TSV file containing all the vendors in the system is then exported
"""
dir_path = GeneralUtils.choose_directory()
if dir_path:
self.export_vendors_tsv(dir_path)
def populate_edit_vendor_view(self):
"""Populates the edit vendor view with the selected vendors's information"""
if self.selected_index >= 0:
selected_vendor = self.vendors[self.selected_index]
self.name_line_edit.textChanged.connect(
lambda new_name: self.on_name_text_changed(new_name, selected_vendor.name, self.name_validation_label))
self.name_line_edit.setText(selected_vendor.name)
self.base_url_line_edit.textChanged.connect(
lambda url: self.on_url_text_changed(url, self.url_validation_label))
self.base_url_line_edit.setText(selected_vendor.base_url)
self.customer_id_line_edit.setText(selected_vendor.customer_id)
self.requestor_id_line_edit.setText(selected_vendor.requestor_id)
self.api_key_line_edit.setText(selected_vendor.api_key)
self.platform_line_edit.setText(selected_vendor.platform)
self.non_Sushi_check_box.setChecked(selected_vendor.is_non_sushi)
self.description_text_edit.setPlainText(selected_vendor.description)
self.companies_text_edit.setPlainText(selected_vendor.companies)
self.set_edit_vendor_view_state(True)
else:
self.name_line_edit.textChanged.connect(
lambda new_name: self.on_name_text_changed(new_name, "", self.name_validation_label, False))
self.name_line_edit.setText("")
self.name_line_edit.textChanged.emit("") # Hide validation_label if showing
self.base_url_line_edit.textChanged.connect(
lambda url: self.on_url_text_changed(url, self.url_validation_label, False))
self.base_url_line_edit.setText("")
self.base_url_line_edit.textChanged.emit("")
self.customer_id_line_edit.setText("")
self.base_url_line_edit.setText("")
self.requestor_id_line_edit.setText("")
self.api_key_line_edit.setText("")
self.platform_line_edit.setText("")
self.non_Sushi_check_box.setChecked(False)
self.description_text_edit.setPlainText("")
self.companies_text_edit.setPlainText("")
self.set_edit_vendor_view_state(False)
def set_edit_vendor_view_state(self, is_enabled):
"""Enables or disables the elements in the edit vendor view
:param is_enabled: This indicates whether the edit vendor view should be enabled
"""
if is_enabled:
self.edit_vendor_details_frame.setEnabled(True)
self.edit_vendor_options_frame.setEnabled(True)
else:
self.edit_vendor_details_frame.setEnabled(False)
self.edit_vendor_options_frame.setEnabled(False)
def on_remove_vendor_clicked(self):
"""Handles the signal emitted when the remove vendor button is clicked.
A confirmation dialog is shown to confirm the removal of the vendor. The vendor is removed from the system if
confirmed
"""
dialog_remove = QDialog()
dialog_remove_ui = RemoveVendorDialog.Ui_dialog_remove()
dialog_remove_ui.setupUi(dialog_remove)
def remove_vendor():
if self.selected_index >= 0:
self.vendors.pop(self.selected_index)
self.selected_index = -1
self.update_vendors_ui()
self.update_vendor_names()
self.populate_edit_vendor_view()
self.vendors_changed_signal.emit(self.vendors)
self.save_all_vendors_to_disk()
button_box = dialog_remove_ui.buttonBox
button_box.accepted.connect(remove_vendor)
dialog_remove.exec_()
def save_all_vendors_to_disk(self):
"""Saves all the vendors in the system to disk"""
json_string = json.dumps(self.vendors, default=lambda o: o.__dict__, indent=4)
GeneralUtils.save_json_file(VENDORS_FILE_DIR, VENDORS_FILE_NAME, json_string)
def sort_vendors(self):
"""Sorts the vendors alphabetically based their names"""
self.vendors = sorted(self.vendors, key=lambda vendor: vendor.name.lower())
def import_vendors_tsv(self, file_path):
"""Imports the vendors in a TSV file path to the system
:param file_path: The file path of the vendors TSV file
"""
try:
tsv_file = open(file_path, 'r', encoding="utf-8", newline='')
reader = csv.DictReader(tsv_file, delimiter='\t')
for row in reader:
if 'is_non_sushi' in row:
is_non_sushi = row['is_non_sushi'].lower() == "true"
else:
is_non_sushi = False
vendor = Vendor(row['name'] if 'name' in row else "",
row['base_url'] if 'base_url' in row else "",
row['customer_id'] if 'customer_id' in row else "",
row['requestor_id'] if 'requestor_id' in row else "",
row['api_key'] if 'api_key' in row else "",
row['platform'] if 'platform' in row else "",
is_non_sushi,
row['description'] if 'description' in row else "",
row['companies'] if 'companies' in row else "")
is_valid, message = self.add_vendor(vendor)
if not is_valid:
if self.settings.show_debug_messages: print(message)
tsv_file.close()
self.sort_vendors()
self.selected_index = -1
self.update_vendors_ui()
self.update_vendor_names()
self.populate_edit_vendor_view()
self.vendors_changed_signal.emit(self.vendors)
self.save_all_vendors_to_disk()
GeneralUtils.show_message(f"Import successful!")
except Exception as e:
if self.settings.show_debug_messages: print(f"File import failed: {e}")
GeneralUtils.show_message(f"File import failed: {e}")
def export_vendors_tsv(self, dir_path):
"""Exports all vendor information as a TSV file to a directory
:param dir_path: The directory path to export the vendors TSV file to
"""
file_path = f"{dir_path}{EXPORT_VENDORS_FILE_NAME}"
column_names = ["name",
"base_url",
"customer_id",
"requestor_id",
"api_key",
"platform",
"is_non_sushi",
"description",
"companies"]
try:
tsv_file = open(file_path, 'w', encoding="utf-8", newline='')
tsv_dict_writer = csv.DictWriter(tsv_file, column_names, delimiter='\t')
tsv_dict_writer.writeheader()
for vendor in self.vendors:
tsv_dict_writer.writerow(vendor.__dict__)
tsv_file.close()
GeneralUtils.show_message(f"Exported to {file_path}")
except Exception as e:
if self.settings.show_debug_messages: print(f"File export failed: {e}")
GeneralUtils.show_message(f"File export failed: {e}")

11
PyToExecutable.py

@ -0,0 +1,11 @@
import PyInstaller.__main__
from os import path
if __name__ == "__main__":
PyInstaller.__main__.run([
'--name=Counter 5 Report Tool',
'--onefile',
'--console',
'--icon=%s' % path.join('main_icon.ico'),
path.join('MainDriver.py'),
])

75
README.md

@ -0,0 +1,75 @@
# COUNTER 5 Report Tool
This project uses the SUSHI API to request usage reports from library vendors. The JSON data received is used to generate TSV reports that follow the COUNTER 5 standards.
The project is written with Python 3.7. The PyQt GUI framework is used to create a user friendly (hopefully) GUI.
## Features
- Manage library vendor credentials
- Fetch reports that strictly adhere to the COUNTER 5 standards
- Fetch customized reports using the available parameters in the SUSHI API
- Import COUNTER 5 reports into the local directories and database
- Specify the costs of subscribed items
- Search the sqlite database of fetched and imported reports
- Generate charts using the data in the database
## Download Project
https://github.com/CS-4820-Library-Project/Libly/releases
## Developer Documentation
https://counter-5-report-tool.readthedocs.io/en/latest/
## How to use pyinstaller for executables
https://github.com/CS-4820-Library-Project/Libly/blob/master/docs/pyinstaller-how-to.md
## Setup Instructions (Windows)
- Install Python 3.8.2 [https://www.python.org/ftp/python/3.8.2/python-3.8.2-amd64.exe]
### Add Python to environment variables [https://datatofish.com/add-python-to-windows-path/]
- Open control panel
- System and Security -> System -> Advanced System Settings -> Advanced -> Environment Variables
- System Variables: Click on Path, Click Edit...
- Click Browse
- Browse to where python is downloaded, by default: C:\Users\USER_NAME\AppData\Local\Programs\Python\Python38
- Add another variable in the same way that we just did.
- Except this time set the filepath to C:\Users\apjm4\AppData\Local\Programs\Python\Python38\Scripts
Python should now be accessible in Windows Command Prompt.
Open command prompt and type Python --version. This should return the version of python that is installed.
If not the path may be wrong or python was not installed correctly.
type pip -v into command prompt, this should return the version of PIP that is installed with Python.
### Download the project from Github
- Close and re-open command prompt
- type cd
- Open the location you downloaded the project to and drag the folder into the command prompt window
- Your command prompt window should now show "C:\Users\NAME>cd C:\Users\NAME\DOWNLOAD_LOCATION
- Hit ENTER
- type: pip install -r requirements.txt
- This installs all the neccessary packages to run the project.
### Run the project
- Type: python maindriver.py
- A User-Interface window should open with the project working
- To run the project from now on, you only need to double click or right click and open MainDriver.py and the project should open
## Developer Setup (using Anaconda and Pycharm)
- Download and install Anaconda: https://www.anaconda.com/distribution/#download-section
- Download and install PyCharm: https://www.jetbrains.com/pycharm/download/
### Using Anaconda
- Launch Anaconda Navigator (Anaconda GUI)
- Go to Environments on the left pane
- Search for and ensure that pyqt and requests packages are installed
### Using PyCharm
- Download and open the project using PyCharm
- Go to File->Settings
- On the left pane, select Project->Project Interpreter
- Click the cog wheel on the right of the project interpreter drop down, click add
- Choose Existing environment and set the location to anaconda_install_location/python.exe, OK, OK
- Allow the IDE to complete set up then launch the program from MainDriver.py. There should be a play icon next to the line "if __name__ == "__main__":"
- We Good To Go!

21
Resources.qrc

@ -0,0 +1,21 @@
<RCC>
<qresource>
<file>ui/resources/main_icon.png</file>
<file>ui/resources/help_icon.png</file>
<file>ui/resources/undo_icon.png</file>
<file>ui/resources/save_icon.png</file>
<file>ui/resources/add_vendor_icon.png</file>
<file>ui/resources/export_vendors_icon.png</file>
<file>ui/resources/import_vendors_icon.png</file>
<file>ui/resources/remove_vendor_icon.png</file>
<file>ui/resources/folder_icon.png</file>
<file>ui/resources/tab_icons/costs_icon.png</file>
<file>ui/resources/tab_icons/fetch_reports_icon.png</file>
<file>ui/resources/tab_icons/fetch_special_reports_icon.png</file>
<file>ui/resources/tab_icons/import_report_icon.png</file>
<file>ui/resources/tab_icons/manage_vendors_icon.png</file>
<file>ui/resources/tab_icons/search_icon.png</file>
<file>ui/resources/tab_icons/settings_icon.png</file>
<file>ui/resources/tab_icons/visual_icon.png</file>
</qresource>
</RCC>

5902
Resources_rc.py

File diff suppressed because it is too large Load Diff

301
Search.py

@ -0,0 +1,301 @@
import os
import sip
import json
from typing import Tuple, Dict
from PyQt5.QtGui import QIntValidator, QDoubleValidator
from PyQt5.QtWidgets import QFrame, QVBoxLayout, QComboBox, QLineEdit, QSpacerItem, QSizePolicy, QLabel
import ManageDB
from Settings import SettingsModel
from ui import SearchTab, SearchAndFrame, SearchOrFrame
from Constants import *
from GeneralUtils import *
class SearchController:
"""Controls the Search tab
:param search_ui: the UI for the search_widget
:param settings: the user's settings"""
def __init__(self, search_ui: SearchTab.Ui_search_tab, settings: SettingsModel):
self.main_window = search_ui
self.settings = settings
# set up report types combobox
self.report_parameter = search_ui.search_report_parameter_combobox
self.report_parameter.addItems(ALL_REPORTS)
# set up start year dateedit
self.start_year_parameter = search_ui.search_start_year_parameter_dateedit
self.start_year_parameter.setDate(QDate.currentDate())
# set up end year dateedit
self.end_year_parameter = search_ui.search_end_year_parameter_dateedit
self.end_year_parameter.setDate(QDate.currentDate())
# set up search button
self.search_button = search_ui.search_button
self.search_button.clicked.connect(self.search)
self.open_results_file_checkbox = search_ui.search_open_file_checkbox
self.open_results_folder_checkbox = search_ui.search_open_folder_checkbox
# set up export button
self.export_button = search_ui.search_export_button
self.export_button.clicked.connect(self.export_parameters)
# set up import button
self.import_button = search_ui.search_import_button
self.import_button.clicked.connect(self.import_parameters)
# set up add and clause button
def add_and_and_or_clause():
"""Invoked to add an and clause containing an or clause to the search"""
and_clause = self.add_and_clause()
self.add_or_clause(and_clause)
self.hide_or_label_in_first_or_clause(and_clause)
self.hide_and_label_in_first_and_clause()
self.add_and_button = search_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():
"""Resets the search clauses, then adds an and clause containing an or clause"""
self.refresh_clauses()
add_and_and_or_clause()
self.report_parameter.currentTextChanged.connect(refresh_and_add_clauses)
self.and_clause_parameters_scrollarea = search_ui.search_and_clause_parameters_scrollarea
self.and_clause_parameters_frame = None
refresh_and_add_clauses()
def update_settings(self, settings: SettingsModel):
"""Called when the settings are saved
:param settings: the new settings"""
self.settings = settings
def refresh_clauses(self):
"""Resets the search clauses"""
self.and_clause_parameters_frame = QFrame()
self.and_clause_parameters_frame.setLayout(QVBoxLayout())
self.and_clause_parameters_frame.layout().addItem(QSpacerItem(0, 0, QSizePolicy.Expanding,
QSizePolicy.Expanding))
self.and_clause_parameters_scrollarea.setWidget(self.and_clause_parameters_frame)
def add_and_clause(self) -> SearchAndFrame.Ui_search_and_clause_parameter_frame:
"""Adds an and clause to the search"""
and_clause = QFrame()
and_clause_ui = SearchAndFrame.Ui_search_and_clause_parameter_frame()
and_clause_ui.setupUi(and_clause)
# set up add or clause button
def add_or_to_this_and():
"""Adds an or clause to this and clause"""
self.add_or_clause(and_clause_ui)
self.hide_or_label_in_first_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():
"""Removes this and clause"""
self.and_clause_parameters_frame.layout().removeWidget(and_clause)
sip.delete(and_clause)
self.hide_and_label_in_first_and_clause()
self.and_clause_parameters_frame.repaint()
and_clause_ui.search_remove_and_clause_button.clicked.connect(remove_this_and)
# add to the layout
self.and_clause_parameters_frame.layout().insertWidget(self.and_clause_parameters_frame.layout().count() - 1,
and_clause)
return and_clause_ui
def hide_and_label_in_first_and_clause(self):
"""Hides the and label for the first and clause in the search"""
and_clause = self.and_clause_parameters_frame.findChild(QFrame, 'search_and_clause_parameter_frame')
if and_clause:
and_clause.findChild(QLabel, "search_and_label").hide()
def add_or_clause(self, and_clause: SearchAndFrame.Ui_search_and_clause_parameter_frame) \
-> SearchOrFrame.Ui_search_or_clause_parameter_frame:
"""Adds an or clause to the search
:param and_clause: the and clause the or clause is added to"""
or_clause = QFrame()
or_clause_ui = SearchOrFrame.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_view_report_fields_list(self.report_parameter.currentText()):
if field[NAME_KEY] not in FIELDS_NOT_IN_SEARCH_DROPDOWN:
field_combobox.addItem(field[NAME_KEY], field['type'])
type_label = or_clause_ui.search_type_label
value_lineedit = or_clause_ui.search_value_parameter_lineedit
def on_field_changed():
"""Invoked when the field parameter is changed"""
type_label.setText(field_combobox.currentData().capitalize() + " Input")
value_lineedit.setText(None)
if field_combobox.currentData() == 'INTEGER':
value_lineedit.setValidator(QIntValidator())
elif field_combobox.currentData() == 'REAL':
value_lineedit.setValidator(QDoubleValidator())
else:
value_lineedit.setValidator(None)
field_combobox.currentTextChanged.connect(on_field_changed)
on_field_changed()
# fill comparison operator combobox
comparison_combobox = or_clause_ui.search_comparison_parameter_combobox
comparison_combobox.addItems(COMPARISON_OPERATORS)
comparison_combobox.addItems(NON_COMPARISONS)
def on_comparison_changed():
"""Invoked when the comparison parameter is changed"""
if comparison_combobox.currentText() in NON_COMPARISONS:
value_lineedit.setText(None)
value_lineedit.setEnabled(False)
else:
value_lineedit.setEnabled(True)
comparison_combobox.currentTextChanged.connect(on_comparison_changed)
# set up remove current or clause button
def remove_this_or():
"""Removes this or clause"""
and_clause.search_or_clause_parameters_frame.layout().removeWidget(or_clause)
sip.delete(or_clause)
self.hide_or_label_in_first_or_clause(and_clause)
and_clause.search_or_clause_parameters_frame.repaint()
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 hide_or_label_in_first_or_clause(self, and_clause: SearchAndFrame.Ui_search_and_clause_parameter_frame):
"""Hides the or label for the first or clause in an and clause
:param and_clause: the and clause"""
or_clause = and_clause.search_or_clause_parameters_frame.findChild(QFrame, 'search_or_clause_parameter_frame')
if or_clause:
or_clause.findChild(QLabel, "search_or_label").hide()
def export_parameters(self):
"""Exports the current search parameters to the selected file"""
file_name = choose_save(JSON_FILTER)
if file_name != '':
if not file_name.lower().endswith('.dat'):
file_name += '.dat'
report, start_year, end_year, search_parameters = self.get_search_parameters()
file = open(file_name, 'w', encoding='utf-8-sig')
if file.mode == 'w':
json.dump({'report': report, 'start_year': start_year, 'end_year': end_year,
'search_parameters': search_parameters}, file)
show_message('Search saved to ' + file_name)
else:
print('Error, no file location selected')
def import_parameters(self):
"""Imports a new set of search parameters from the selected file"""
file_name = choose_file(JSON_FILTER)
if file_name != '':
fields = json.loads(read_json_file(file_name))
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']
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_KEY])
or_clause.search_comparison_parameter_combobox.setCurrentText(sub_clause[COMPARISON_KEY])
or_clause.search_value_parameter_lineedit.setText(str(sub_clause[VALUE_KEY]))
def search(self):
"""Queries the database based on the current search parameters and saves the results to the selected file"""
report, start_year, end_year, search_parameters = self.get_search_parameters()
# sql query to get search results
sql_text, data = ManageDB.search_sql_text(report, start_year, end_year, search_parameters)
headers = []
for field in ManageDB.get_view_report_fields_list(report):
headers.append(field[NAME_KEY])
file_name = choose_save(TSV_FILTER)
if file_name != '':
if not file_name.lower().endswith('.tsv'):
file_name += '.tsv'
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
results = ManageDB.run_select_sql(connection, sql_text, data)
connection.close()
results.insert(0, headers)
if self.settings.show_debug_messages: print(results)
save_data_as_tsv(file_name, results)
if self.open_results_folder_checkbox.isChecked():
open_file_or_dir(os.path.dirname(file_name))
if self.open_results_file_checkbox.isChecked():
open_file_or_dir(file_name)
if not self.open_results_file_checkbox.isChecked():
show_message('Results saved to ' + file_name)
else:
print('Error, no connection')
else:
print('Error, no file location selected')
def get_search_parameters(self) -> Tuple[str, int, int, Sequence[Sequence[Dict[str, Any]]]]:
"""Reads the current search parameters from the UI
:returns: (report, start_year, end_year, search_parameters) a Tuple with the kind of report selected, the
starting year selected, the ending year selected, and a list of the search parameters in POS form (and of
ors)"""
# 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_frame.findChildren(QFrame, 'search_and_clause_parameter_frame'):
# iterate over and clauses
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
# get parameters for clause
field_parameter_combobox = or_widget.findChild(QComboBox, 'search_field_parameter_combobox')
field_parameter = field_parameter_combobox.currentText()
comparison_parameter_combobox = or_widget.findChild(QComboBox, 'search_comparison_parameter_combobox')
comparison_parameter = comparison_parameter_combobox.currentText()
value_parameter_lineedit = or_widget.findChild(QLineEdit, 'search_value_parameter_lineedit')
value_parameter = None
if comparison_parameter in NON_COMPARISONS:
pass
elif field_parameter_combobox.currentData() == 'INTEGER':
value_parameter = int(value_parameter_lineedit.text())
elif field_parameter_combobox.currentData() == 'REAL':
value_parameter = float(value_parameter_lineedit.text())
else:
value_parameter = value_parameter_lineedit.text()
or_clauses.append(
{FIELD_KEY: field_parameter, COMPARISON_KEY: comparison_parameter, VALUE_KEY: value_parameter})
search_parameters.append(or_clauses)
return report, start_year, end_year, search_parameters

213
Settings.py

@ -0,0 +1,213 @@
"""This module handles all operations involving the user's settings."""
import json
from os import path
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import QObject, pyqtSignal
from ui import SettingsTab
import ManageDB
from Constants import *
import GeneralUtils
from GeneralUtils import JsonModel
class Setting(Enum):
"""An enum of all settings"""
YEARLY_DIR = 0
OTHER_DIR = 1
REQUEST_INTERVAL = 2
REQUEST_TIMEOUT = 3
CONCURRENT_VENDORS = 4
CONCURRENT_REPORTS = 5
USER_AGENT = 6
class SettingsModel(JsonModel):
"""This holds the user's settings.
:param yearly_directory: The directory where yearly reports are saved. Yearly reports are reports that include all
the available data for a year.
:param other_directory: The default directory where non-yearly reports are saved.
:param request_interval: The time to wait between each report request, per vendor.
:param request_timeout: The time to wait before timing out a connection (seconds).
:param concurrent_vendors: The max number of vendors to work on at a time.
:param concurrent_reports: The max number of reports to work on at a time, per vendor.
:param user_agent: The user-agent that's included in the header when making requests.
"""
def __init__(self, show_debug_messages: bool, yearly_directory: str, other_directory: str, request_interval: int,
request_timeout: int, concurrent_vendors: int, concurrent_reports: int, user_agent: str,
default_currency: str):
self.show_debug_messages = show_debug_messages
self.yearly_directory = path.abspath(yearly_directory) + path.sep
self.other_directory = path.abspath(other_directory) + path.sep
self.request_interval = request_interval
self.request_timeout = request_timeout
self.concurrent_vendors = concurrent_vendors
self.concurrent_reports = concurrent_reports
self.user_agent = user_agent
self.default_currency = default_currency
@classmethod
def from_json(cls, json_dict: dict):
show_debug_messages = json_dict["show_debug_messages"]\
if "show_debug_messages" in json_dict else SHOW_DEBUG_MESSAGES
yearly_directory = json_dict["yearly_directory"]\
if "yearly_directory" in json_dict else YEARLY_DIR
other_directory = json_dict["other_directory"]\
if "other_directory" in json_dict else OTHER_DIR
request_interval = int(json_dict["request_interval"])\
if "request_interval" in json_dict else REQUEST_INTERVAL
request_timeout = int(json_dict["request_timeout"])\
if "request_timeout" in json_dict else REQUEST_TIMEOUT
concurrent_vendors = int(json_dict["concurrent_vendors"])\
if "concurrent_vendors" in json_dict else CONCURRENT_VENDORS
concurrent_reports = int(json_dict["concurrent_reports"])\
if "concurrent_reports" in json_dict else CONCURRENT_REPORTS
user_agent = json_dict["user_agent"]\
if "user_agent" in json_dict else USER_AGENT
default_currency = json_dict["default_currency"]\
if "default_currency" in json_dict else DEFAULT_CURRENCY
return cls(show_debug_messages, yearly_directory, other_directory, request_interval, request_timeout,
concurrent_vendors, concurrent_reports, user_agent, default_currency)
class SettingsController(QObject):
"""Controls the Settings tab
:param settings_widget: The settings widget.
:param settings_ui: The UI for settings_widget.
"""
settings_changed_signal = pyqtSignal(SettingsModel)
def __init__(self, settings_widget: QWidget, settings_ui: SettingsTab.Ui_settings_tab):
# region General
super().__init__()
self.settings_widget = settings_widget
json_string = GeneralUtils.read_json_file(SETTINGS_FILE_DIR + SETTINGS_FILE_NAME)
json_dict = json.loads(json_string)
self.settings = SettingsModel.from_json(json_dict)
self.show_debug_checkbox = settings_ui.show_debug_check_box
self.show_debug_checkbox.setChecked(self.settings.show_debug_messages)
# endregion
# region Reports
self.yearly_dir_edit = settings_ui.yearly_directory_edit
self.other_dir_edit = settings_ui.other_directory_edit
self.request_interval_spin_box = settings_ui.request_interval_spin_box
self.request_timeout_spin_box = settings_ui.request_timeout_spin_box
self.concurrent_vendors_spin_box = settings_ui.concurrent_vendors_spin_box
self.concurrent_reports_spin_box = settings_ui.concurrent_reports_spin_box
self.user_agent_edit = settings_ui.user_agent_edit
self.yearly_dir_edit.setText(self.settings.yearly_directory)
self.other_dir_edit.setText(self.settings.other_directory)
self.request_interval_spin_box.setValue(self.settings.request_interval)
self.request_timeout_spin_box.setValue(self.settings.request_timeout)
self.concurrent_vendors_spin_box.setValue(self.settings.concurrent_vendors)
self.concurrent_reports_spin_box.setValue(self.settings.concurrent_reports)
self.user_agent_edit.setText(self.settings.user_agent)
settings_ui.yearly_directory_button.clicked.connect(
lambda: self.on_directory_setting_clicked(Setting.YEARLY_DIR))
settings_ui.other_directory_button.clicked.connect(
lambda: self.on_directory_setting_clicked(Setting.OTHER_DIR))
# Reports Help Messages
settings_ui.yearly_directory_help_button.clicked.connect(
lambda: GeneralUtils.show_message("This is where the calendar-year reports will be saved"))
settings_ui.other_directory_help_button.clicked.connect(
lambda: GeneralUtils.show_message("This is where the special and non-calendar-year date range reports will "
"be saved by default"))
settings_ui.request_interval_help_button.clicked.connect(
lambda: GeneralUtils.show_message("The number of seconds the program will wait between sending each report "
"request to a given vendor"))
settings_ui.request_timeout_help_button.clicked.connect(
lambda: GeneralUtils.show_message("The number of seconds the program will allow a vendor to respond to "
"each report request before canceling it"))
settings_ui.concurrent_vendors_help_button.clicked.connect(
lambda: GeneralUtils.show_message("The maximum number of vendors to work on at the same time. "
"If set too high, the UI might freeze while fetching reports but the "
"fetch process will continue"))
settings_ui.concurrent_reports_help_button.clicked.connect(
lambda: GeneralUtils.show_message("The maximum number of reports to work on at the same time (per vendor). "
"If set too high, the UI might freeze while fetching reports but the "
"fetch process will continue"))
settings_ui.user_agent_help_button.clicked.connect(
lambda: GeneralUtils.show_message("How program identifies itself to the SUSHI servers. Some vendors will "
"reject some particular user agents. Only change this if there is a "
"known problem as it will affect all requests to all vendors. "
"See Help for more information."))
settings_ui.default_currency_help_button.clicked.connect(
lambda: GeneralUtils.show_message("The currency shown first in the Costs pulldown and also by Visual to "
"label the local currency in the spreadsheets generated with the Cost "
"Ratio option. Note: This doesn't have to be one of the pre-loaded "
"currencies."))
# endregion
# region Costs
self.default_currency_combobox = settings_ui.settings_costs_default_currency_combobox
self.default_currency_combobox.addItems(CURRENCY_LIST)
self.default_currency_combobox.setCurrentText(self.settings.default_currency)
# endregion
# region Search
# set up restore database button
self.is_rebuilding_database = False
self.update_database_dialog = ManageDB.UpdateDatabaseProgressDialogController(self.settings_widget)
self.rebuild_database_button = settings_ui.settings_rebuild_database_button
self.rebuild_database_button.clicked.connect(self.on_rebuild_database_clicked)
# endregion
settings_ui.save_button.clicked.connect(self.on_save_button_clicked)
def on_directory_setting_clicked(self, setting: Setting):
"""Handles the signal emitted when a choose folder button is clicked
:param setting: The setting to be changed
"""
dir_path = GeneralUtils.choose_directory()
if dir_path:
if setting == Setting.YEARLY_DIR:
self.yearly_dir_edit.setText(dir_path)
elif setting == Setting.OTHER_DIR:
self.other_dir_edit.setText(dir_path)
def on_save_button_clicked(self):
"""Handles the signal emitted when the save button is clicked"""
self.update_settings()
self.save_settings_to_disk()
self.settings_changed_signal.emit(self.settings)
GeneralUtils.show_message("Changes saved!")
def on_rebuild_database_clicked(self):
"""Restores the database when the restore database button is clicked"""
if not self.is_rebuilding_database: # check if already running
if GeneralUtils.ask_confirmation('Are you sure you want to rebuild the database?'):
self.is_rebuilding_database = True
self.update_database_dialog.update_database(ManageDB.get_all_report_files() +
ManageDB.get_all_cost_files(),
True)
self.is_rebuilding_database = False
else:
if self.settings.show_debug_messages: print('Database is already being rebuilt')
def update_settings(self):
"""Updates the app's settings using the values entered on the UI"""
self.settings.show_debug_messages = self.show_debug_checkbox.isChecked()
self.settings.yearly_directory = self.yearly_dir_edit.text()
self.settings.other_directory = self.other_dir_edit.text()
self.settings.request_interval = self.request_interval_spin_box.value()
self.settings.request_timeout = self.request_timeout_spin_box.value()
self.settings.concurrent_vendors = self.concurrent_vendors_spin_box.value()
self.settings.concurrent_reports = self.concurrent_reports_spin_box.value()
self.settings.user_agent = self.user_agent_edit.text()
self.settings.default_currency = self.default_currency_combobox.currentText()
def save_settings_to_disk(self):
"""Saves all settings to disk"""
json_string = json.dumps(self.settings, default=lambda o: o.__dict__)
GeneralUtils.save_json_file(SETTINGS_FILE_DIR, SETTINGS_FILE_NAME, json_string)

757
Visual.py

@ -0,0 +1,757 @@
"""This module handles all operations involving the visual tab."""
import calendar
import datetime
import json
import os
from _operator import itemgetter
from typing import Sequence
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QFont
import xlsxwriter
from datetime import date
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QFileDialog, QDialog
import GeneralUtils
from GeneralUtils import *
import ManageDB
import ManageVendors
from Settings import SettingsModel
from ui import MessageDialog, VisualTab
from Constants import *
class VisualController:
"""Controls the Visual tab
:param visual_ui: The UI for visual_widget.
"""
def __init__(self, visual_ui: VisualTab.Ui_visual_tab, settings: SettingsModel):
self.settings = settings
# set up and configure report type combobox
self.report_parameter = visual_ui.search_report_parameter_combobox_2
self.report_parameter.addItems(ALL_REPORTS)
self.report_parameter.currentTextChanged[str].connect(self.on_report_parameter_changed)
# set up and configure cost ratio combobox
self.cost_parameter = visual_ui.cost_ratio_option_combobox
COST_TYPE_ALL = ('Cost in Local Currency with Tax', 'Cost in Local Currency', 'Cost in Original Currency')
self.cost_parameter.addItems(COST_TYPE_ALL)
# set up and configure cost ratio frame
self.frame_cost = visual_ui.edit_cost_ratio_frame
self.frame_cost.setEnabled(False)
# set up and configure top num frame
self.top_num_frame = visual_ui.edit_top_num_frame
self.top_num_frame.setEnabled(False)
# set up top num spinbox and configure lower and upper bounds
self.top_num_edit = visual_ui.top_num_spinbox
# set up chart type radio buttons
self.h_bar_radio = visual_ui.radioButton
self.v_bar_radio = visual_ui.radioButton_3
self.line_radio = visual_ui.radioButton_4
self.v_bar_radio.setChecked(True)
# set up calculations type radio buttons
self.monthly_radio = visual_ui.monthly_radioButton
self.yearly_radio = visual_ui.yearly_radioButton
self.topNum_radio = visual_ui.topnum_radioButton
self.costRatio_radio = visual_ui.costratio_radioButton
# configure calculation type radio buttons and connect with method
self.monthly_radio.setChecked(True)
self.monthly_radio.toggled.connect(self.on_calculation_type_changed)
self.yearly_radio.toggled.connect(self.on_calculation_type_changed)
self.topNum_radio.toggled.connect(self.on_calculation_type_changed)
self.costRatio_radio.toggled.connect(self.on_calculation_type_changed)
# set up start year dateedit
self.start_year_parameter = visual_ui.search_start_year_parameter_dateedit_2
self.start_year_parameter.setDate(date.today())
# set up end year dateedit
self.end_year_parameter = visual_ui.search_end_year_parameter_dateedit_2
self.end_year_parameter.setDate(date.today())
# set up name label
self.name_label = visual_ui.visual_name_label
# set up name combobox
self.name_combobox = visual_ui.visual_name_parameter_combobox
self.name = None
self.metric = visual_ui.metric_Type_comboBox
self.metric.addItems(DATABASE_REPORTS_METRIC)
self.vendor = visual_ui.visual_vendor_parameter_combobox
self.vendor.currentTextChanged.connect(self.on_vendor_changed)
self.vendor_parameter = None
self.vendor_parameter = self.vendor.currentText()
vendors_json_string = GeneralUtils.read_json_file(ManageVendors.VENDORS_FILE_PATH)
vendor_dicts = json.loads(vendors_json_string)
self.vendor.clear()
self.vendor.addItem("")
self.vendor.addItems([vendor_dict['name'] for vendor_dict in vendor_dicts])
# set up the search clauses
self.and_clause_parameters = None
# set up create chart button
self.create_chart_button = visual_ui.create_chart_button
self.create_chart_button.clicked.connect(self.createChart)
# set up customize chart field
self.chart_title_edit = visual_ui.chart_title_lineEdit
self.horizontal_axis_edit = visual_ui.horizontal_axis_lineEdit
self.vertical_axis_edit = visual_ui.vertical_axis_lineEdit
# set up open file and open folder check box
self.open_file = visual_ui.open_file_checkBox
self.open_folder = visual_ui.open_folder_checkBox
self.file_name = None
self.data = []
self.temp_results = []
self.top_num = None
self.results = None
self.names = []
self.costs_names = []
def update_settings(self, settings: SettingsModel):
"""Called when the settings are saved
:param settings: the new settings"""
self.settings = settings
self.local_currency = self.settings.default_currency
#self.load_currency_list()
def database_updated(self, code: int):
"""Called when the database is updated
:param code: the exit code of the update"""
self.fill_names()
def load_vendor_list(self, vendors: Sequence[ManageVendors.Vendor]):
"""Updates the vendor list combobox
:param vendors: the new list of vendors"""
self.vendor.clear()
self.vendor.addItem("")
self.vendor.addItems([vendor.name for vendor in vendors])
def on_calculation_type_changed(self):
"""Invoke when calculation type is changed"""
if self.topNum_radio.isChecked():
self.top_num_frame.setEnabled(True)
self.frame_cost.setEnabled(False)
self.name_combobox.setEnabled(False)
self.name_label.setEnabled(False)
if self.costRatio_radio.isChecked():
self.top_num_frame.setEnabled(False)
self.frame_cost.setEnabled(True)
self.name_combobox.setEnabled(True)
self.name_label.setEnabled(True)
if self.monthly_radio.isChecked() or self.yearly_radio.isChecked():
self.top_num_frame.setEnabled(False)
self.frame_cost.setEnabled(False)
self.name_combobox.setEnabled(True)
self.name_label.setEnabled(True)
def on_report_parameter_changed(self, text):
"""Invoke when report type is changed"""
self.metric.clear()
if text in DATABASE_REPORTS:
self.metric.addItems(DATABASE_REPORTS_METRIC)
self.name_label.setText('Database')
if text in ITEM_REPORTS:
self.metric.addItems(ITEM_REPORTS_METRIC)
self.name_label.setText('Item')
if text in PLATFORM_REPORTS:
self.metric.addItems(PLATFORM_REPORTS_METRIC)
self.name_label.setText('Platform')
if text in TITLE_REPORTS:
self.metric.addItems(TITLE_REPORTS_METRIC)
self.name_label.setText('Title')
if self.vendor.currentText():
self.fill_names()
def on_vendor_changed(self):
"""Invoke when vendor is changed"""
self.vendor_parameter = self.vendor.currentText()
if self.report_parameter.currentText():
self.fill_names()
def fill_names(self, only_get_costs_names: bool = False):
"""Fill name field combobox"""
self.name_combobox.clear()
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
if not only_get_costs_names:
names_sql_text, names_data = ManageDB.get_names_sql_text(self.report_parameter.currentText(), self.vendor_parameter)
names_results = ManageDB.run_select_sql(connection, names_sql_text, names_data)
if names_results:
self.names = [result[0] for result in names_results]
else:
self.names = []
if self.settings.show_debug_messages: print(names_results)
costs_sql_text, costs_data = ManageDB.get_names_with_costs_sql_text(self.report_parameter.currentText(),
self.vendor_parameter,
int(self.start_year_parameter.text()),
int(self.end_year_parameter.text()))
costs_results = ManageDB.run_select_sql(connection, costs_sql_text, costs_data)
if costs_results:
self.costs_names = [result[0] for result in costs_results]
else:
self.costs_names = []
if self.settings.show_debug_messages: print(costs_results)
connection.close()
model = QStandardItemModel()
for name in self.names:
item = QStandardItem(name)
if name in self.costs_names:
font = QFont()
font.setBold(True)
item.setFont(font)
model.appendRow(item)
self.name_combobox.setModel(model)
else:
print('Error, no connection')
# submit search result to database and open results
def createChart(self):
"""Invoke when user click on create chart"""
# get report type
report = self.report_parameter.currentText()
# get start year
start_year = self.start_year_parameter.text()
# get end year
end_year = self.end_year_parameter.text()
# get name
name = self.name_combobox.currentText()
# get metric
metric = self.metric.currentText()
# get vendor
vendor = self.vendor.currentText()
self.top_num = -1
self.temp_results = []
message = ""
message1 = ""
message2 = ""
message3 = ""
message4 = ""
if name == "" and self.topNum_radio.isChecked() == False:
message4 = "- Enter/Choose " + self.name_label.text() + "\n"
if vendor == "" and self.topNum_radio.isChecked() == False:
message1 = "- Choose a Vendor \n"
if start_year > end_year or (int(start_year) > datetime.datetime.now().year or int(end_year) > datetime.datetime.now().year) :
currentYear = datetime.datetime.now().year
message3 = "- Start Year must be less than End Year and they cannot be greater than " + str(
currentYear) + "\n"
message = message1 + message4 + message3
if message != "":
message = "To Create Chart check the following: \n" + message
GeneralUtils.show_message(message)
if self.monthly_radio.isChecked() and message == "":
# sql query to get search results
sql_text, data = ManageDB.monthly_chart_search_sql_text(report, start_year, end_year, name, metric, vendor)
print(sql_text) # testing
headers = tuple([field['name'] for field in ManageDB.get_monthly_chart_report_fields_list(report)])
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
self.results = ManageDB.run_select_sql(connection, sql_text, data)
print(self.results)
self.results.insert(0, headers)
print(self.results)
connection.close()
else:
print('Error, no connection')
if len(self.results) > 1 and self.monthly_radio.isChecked():
self.process_default_data()
self.open_file_folder()
if name != "" and start_year <= end_year and len(self.results) <= 1:
message4 = name + " of " + metric + " NOT FOUND in " + report + " for the chosen year range!"
GeneralUtils.show_message(message4)
if self.yearly_radio.isChecked() and message == "":
# sql query to get search results
sql_text, data = ManageDB.yearly_chart_search_sql_text(report, start_year, end_year, name, metric, vendor)
print(sql_text) # testing
headers = tuple([field['name'] for field in ManageDB.get_yearly_chart_report_fields_list(report)])
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
self.results = ManageDB.run_select_sql(connection, sql_text, data)
print(self.results)
self.results.insert(0, headers)
print(self.results)
connection.close()
else:
print('Error, no connection')
if len(self.results) > 1 and self.yearly_radio.isChecked():
self.process_yearly_data()
self.open_file_folder()
if name != "" and start_year <= end_year and len(self.results) <= 1:
message4 = name + " of " + metric + " NOT FOUND in " + report + " for the chosen year range!"
GeneralUtils.show_message(message4)
if self.costRatio_radio.isChecked() and message == "":
# sql query to get search results
sql_text, data = ManageDB.cost_chart_search_sql_text(report, start_year, end_year, name, metric, vendor)
print(sql_text) # testing
headers = tuple([field['name'] for field in ManageDB.get_cost_chart_report_fields_list(report)])
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
self.results = ManageDB.run_select_sql(connection, sql_text, data)
print(self.results)
self.results.insert(0, headers)
print(self.results)
connection.close()
else:
print('Error, no connection')
if len(self.results) > 1 and self.costRatio_radio.isChecked():
self.process_cost_ratio_data()
self.open_file_folder()
if name != "" and start_year <= end_year and len(self.results) <= 1:
message4 = name + " of " + metric + " NOT FOUND in " + report + " for the chosen year range!"
GeneralUtils.show_message(message4)
if self.topNum_radio.isChecked() and message == "":
self.top_num = int(self.top_num_edit.text())
if self.top_num == 0:
self.top_num = None
if self.vendor.currentText() == "":
vendor = None
sql_text, data = ManageDB.top_number_chart_search_sql_text(report, start_year, end_year, metric, vendor,
self.top_num)
headers = tuple([field['name'] for field in ManageDB.get_top_number_chart_report_fields_list(report)])
connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None:
self.results = ManageDB.run_select_sql(connection, sql_text, data)
self.results.insert(0, headers)
connection.close()
else:
print('Error, no connection')
if len(self.results) > 1:
self.process_top_X_data()
self.open_file_folder()
elif start_year <= end_year:
message5 = self.name_label.text() + " of " + metric + " Not Found in " + report + " for the chosen year range!"
GeneralUtils.show_message(message5)
def open_file_folder(self):
"""Invoke to open file or folder"""
if self.open_folder.isChecked():
open_file_or_dir(os.path.dirname(self.file_name))
if self.open_file.isChecked():
open_file_or_dir(self.file_name)
if not self.open_file.isChecked():
show_message('Results saved to ' + self.file_name)
# process_data distributes the usage data for monthly in an array accordingly
def process_default_data(self):
"""Invoked when calculation type: monthly is selected"""
m = len(self.results)
self.legendEntry = [] # legend entry data
for i in range(1, m):
self.legendEntry.append(self.results[i][3])
# data is an array with the sorted usage figures
self.data = []
for i in range(0, m):
data1 = []
n = len(self.results[i])
for j in range(4, n): # from jan to dec only
data1.append(self.results[i][j])
self.data.append(data1)
# testing to make sure its working good
print(self.data[0]) # this is the first column in the excel file/vertical axis data in the chart
print(self.data[1])
print(len(self.data))
self.chart_type()
def process_yearly_data(self):
"""Invoked when calculation type: yearly is selected"""
m = len(self.results)
self.legendEntry = [] # legend entry data
self.legendEntry.append(self.metric.currentText())
# data is an array with the sorted usage figures
self.data = []
data1 = [] # year
data2 = [] # reporting_period_total
for i in range(1, m):
data1.append(self.results[i][3])
self.data.append(data1)
for i in range(1, m):
data2.append(self.results[i][4])
self.data.append(data2)
# testing to make sure its working good
print(self.data[0]) # this is the first column in the excel file/vertical axis data in the chart
print(self.data[1])
print(len(self.data))
self.chart_type()
def process_cost_ratio_data(self):
"""Invoked when calculation type: cost ratio is selected"""
m = len(self.results) #length of self.results
self.legendEntry = [] # legend entry data contains column names
# data is an array of array with year, cost per metric, total and cost in separate arrays
self.data = []
data1 = [] # year
data2 = [] # cost per metric
data3 = [] # reporting_period_total
data4 = [] # cost
# retrieve year and add it to array
for i in range(1, m):
data1.append(self.results[i][3])
self.data.append(data1)
# retrieve cost and total and finding cost per metric and adding it to array
if self.cost_parameter.currentText() == 'Cost in Local Currency with Tax':
self.legendEntry.append('Cost in Local Currency with Tax Per Metric')
self.legendEntry.append('Cost in Local Currency with Tax')
for i in range(1, m):
cost = self.results[i][7]
if self.results[i][7] is None:
cost = 0
data4.append(cost)
data2.append(cost / self.results[i][8])
self.data.append(data2)
self.data.append(data4)
if self.cost_parameter.currentText() == 'Cost in Local Currency':
self.legendEntry.append('Cost in Local Currency Per Metric')
self.legendEntry.append('Cost in Local Currency')
for i in range(1, m):
cost = self.results[i][6]
if self.results[i][6] is None:
cost = 0
data4.append(cost)
data2.append(cost / self.results[i][8])
self.data.append(data2)
self.data.append(data4)
if self.cost_parameter.currentText() == 'Cost in Original Currency':
self.legendEntry.append('Cost in Original Currency Per Metric')
self.legendEntry.append('Cost in Original Currency')
for i in range(1, m):
cost = self.results[i][4]
if self.results[i][4] is None:
cost = 0
data4.append(cost)
data2.append(cost / self.results[i][8])
self.data.append(data2)
self.data.append(data4)
# retrieve reporting_period_total and add it to array
for i in range(1, m):
data3.append(self.results[i][8])
self.data.append(data3)
# add column header to legend entry
self.legendEntry.append(self.metric.currentText())
# testing to see data in array of array
print(self.data[0]) # first column in excel (year)
print(self.data[1]) # second column (cost per metric)
# print(self.data[2]) # third column (cost)
# print(self.data[4]) # fourth column (total)
# print(len(self.data)) #testing
self.chart_type()
def process_top_X_data(self):
"""Invoked when calculation type: top # is selected"""
m = len(self.results)
#print(self.results)
print(m)
self.temp_results = []
self.legendEntry = [] # legend entry data
self.legendEntry.append(self.results[0][3])
self.legendEntry.append(self.results[0][4])
for i in range(1, m):
self.temp_results.append(self.results[i])
self.temp_results = sorted(self.temp_results, key=itemgetter(4))
print(len(self.temp_results))
print(self.temp_results)
n = len(self.temp_results)
# data is an array with the sorted usage figures
self.data = []
data1 = [] # name(database, title,...)
data2 = [] # reporting total
data3 = [] # rankings
data4 = [] # optional vendor column
# get all name(database,title,...)
data = self.temp_results[0][0]
data1.append(data)
for i in range(1, n): # get database
data = self.temp_results[i][0]
data1.append(data)
self.data.append(data1)
print(data1)
# get all reporting total
metri = self.temp_results[0][3]
data2.append(metri)
for i in range(1, n): # get reporting total
metri = self.temp_results[i][3]
data2.append(metri)
self.data.append(data2)
print(data2)
# get all ranking
rank = self.temp_results[0][4]
data3.append(rank)
for i in range(1, n):
rank = self.temp_results[i][4]
data3.append(rank)
self.data.append(data3)
# will add vendor column to chart if the user do not enter anything in vendor
if self.vendor.currentText() == "":
self.legendEntry.append(self.results[0][2])
for i in range(0, n):
rank = self.temp_results[i][2]
data4.append(rank)
self.data.append(data4)
self.chart_type()
# get chart type checked
def chart_type(self):
"""Invoked to determine which chart type is selected by user"""
if self.h_bar_radio.isChecked():
self.horizontal_bar_chart()
if self.v_bar_radio.isChecked():
self.vertical_bar_chart()
if self.line_radio.isChecked():
self.line_chart()
# get file name and titles from user
def customizeChart(self):
"""Invoked to get information from user to customize chart.
It is highly recommended that user write the details like year, report type, calculation type,.. in chart title"""
chart_title = self.chart_title_edit.text()
horizontal_axis_title = self.horizontal_axis_edit.text()
vertical_axis_title = self.vertical_axis_edit.text()
return chart_title, horizontal_axis_title, vertical_axis_title
# add titles to chart and styles
@staticmethod
def add_Customize(chart1, chart_title, horizontal_axis_title, vertical_axis_title):
"""Invoked to add information to customize the chart
:param chart1: the chart to add details to
:param chart_title: the chart title
:param horizontal_axis_title: the horizontal axis title
:param vertical_axis_title: the vertical axis title"""
# Add a chart title and some axis labels.
chart1.set_title({'name': chart_title})
chart1.set_x_axis({'name': horizontal_axis_title})
chart1.set_y_axis({'name': vertical_axis_title})
# Set an Excel chart style.
chart1.set_style(11)
# create file with ext and add sheet to file
def createFile(self):
"""Invoked to create xlsx file"""
self.file_name = choose_save(EXCEL_FILTER)
if self.file_name != '':
if not self.file_name.lower().endswith('.xlsx'):
self.file_name += '.xlsx'
workbook = xlsxwriter.Workbook(self.file_name)
# add sheet to xlsx file
worksheet = workbook.add_worksheet()
return workbook, worksheet
# Add the worksheet data that the charts will refer to.
def populateData(self, vertical_axis_title, worksheet, workbook):
"""Invoked to create xlsx file
:param vertical_axis_title: the vertical axis title
:param worksheet: the worksheet in the xlsx file
:param workbook: the workbook"""
bold = workbook.add_format({'bold': 1})
#headings = [vertical_axis_title]
headings = [""]
for i in range(0, len(self.legendEntry)):
headings.append(self.legendEntry[i])
worksheet.write_row('A1', headings, bold)
worksheet.write_column('A2', self.data[0])
n = ord('A') + 1
if self.costRatio_radio.isChecked() == False:
for i in range(1, len(self.data)):
worksheet.write_column(chr(n) + '2', self.data[i])
n = n + 1
if self.costRatio_radio.isChecked() == True:
# Add a number format for cells with money.
currency = self.process_currency()
money = workbook.add_format({'num_format': currency})
for i in range(1, len(self.data)-1):
worksheet.write_column(chr(n) + '2', self.data[i], money)
n = n + 1
worksheet.write_column(chr(n) + '2', self.data[len(self.data)-1])
# process currency
def process_currency(self):
"""Invoke to determine between local or original currency for cost"""
if self.cost_parameter.currentText() == 'Cost in Local Currency with Tax' or self.cost_parameter.currentText() == 'Cost in Local Currency':
local_currency = self.settings.default_currency
currency = self.get_currency_code(local_currency)
if self.cost_parameter.currentText() == 'Cost in Original Currency':
original_currency = self.results[1][5]
currency = self.get_currency_code(original_currency)
return currency
# return currency code for excel
def get_currency_code(self, local_currency):
"""Invoke to find currency being used"""
if local_currency == 'CAD':
currency = '[$CAD] #,###.#########################_)'
if local_currency == 'USD':
currency = '[$USD] #,###.#########################_)'
if local_currency == 'EUR':
currency = '[$EUR] #,###.#########################_)'
if local_currency == 'JPY':
currency = '[$JPY] #,###.#########################_)'
if local_currency == 'GBP':
currency = '[$GBP] #,###.#########################_)'
if local_currency == 'CHF':
currency = '[$CHF] #,###.#########################_)'
if local_currency == 'AUD':
currency = '[$AUD] #,###.#########################_)'
return currency
# create chart and add series to it
def configureSeries(self, workbook, chart_type):
"""Invoked to create xlsx file
:param workbook: the workbook
:param chart_type: the chart type"""
chart1 = workbook.add_chart({'type': chart_type})
n = len(self.data[0])
# Configure the first series.
chart1.add_series({
'name': '=Sheet1!$B$1',
'categories': '=Sheet1!$A$2:$A$'+str(n+1),
'values': '=Sheet1!$B$2:$B$'+str(n+1),
})
# Configure any subsequent series. Note use of alternative syntax to define ranges.
# no more series will be added if top # and cost ratio are not selected
if self.top_num == -1 and self.costRatio_radio.isChecked() == False:
m = 2
for i in range(2, len(self.data)):
chart1.add_series({
'name': ['Sheet1', 0, m],
'categories': ['Sheet1', 1, 0, n, 0],
'values': ['Sheet1', 1, m, n, m],
})
m = m + 1
return chart1
def horizontal_bar_chart(self):
"""Invoked to create a horizontal bar chart"""
# get titles from customizeChart
chart_title, horizontal_axis_title, vertical_axis_title = self.customizeChart()
# create xlsx file and add sheet file
workbook, worksheet = self.createFile()
# add data to worksheet
self.populateData(vertical_axis_title, worksheet, workbook)
# create horizontal bar chart and add series to it
chart1 = self.configureSeries(workbook, 'bar')
# Add a chart title and some axis labels.
self.add_Customize(chart1, chart_title, horizontal_axis_title, vertical_axis_title)
# Insert the chart into the worksheet (with an offset).
worksheet.insert_chart('F2', chart1, {'x_scale': 2, 'y_scale': 2})
workbook.close()
# Completion message
message_completion = "Done!"
GeneralUtils.show_message(message_completion)
def vertical_bar_chart(self):
"""Invoked to create a vertical bar chart"""
# get titles from customizeChart
chart_title, horizontal_axis_title, vertical_axis_title = self.customizeChart()
# create xlsx file and add sheet file
workbook, worksheet = self.createFile()
# add data to worksheet
self.populateData(vertical_axis_title, worksheet, workbook)
# create horizontal bar chart and add series to it
chart1 = self.configureSeries(workbook, 'column')
# Add a chart title and some axis labels.
self.add_Customize(chart1, chart_title, horizontal_axis_title, vertical_axis_title)
# Insert the chart into the worksheet (with an offset).
worksheet.insert_chart('F2', chart1, {'x_scale': 2, 'y_scale': 2})
workbook.close()
# Completion message
message_completion = "Done!"
GeneralUtils.show_message(message_completion)
def line_chart(self):
"""Invoked to create a line chart"""
# get titles from customizeChart
chart_title, horizontal_axis_title, vertical_axis_title = self.customizeChart()
# create xlsx file and add sheet file
workbook, worksheet = self.createFile()
# Add data to worksheet
self.populateData(vertical_axis_title, worksheet, workbook)
# create horizontal bar chart and add series to it
chart1 = self.configureSeries(workbook, 'line')
# Add a chart title and some axis labels.
self.add_Customize(chart1, chart_title, horizontal_axis_title, vertical_axis_title)
# Insert the chart into the worksheet (with an offset).
worksheet.insert_chart('F2', chart1, {'x_scale': 2, 'y_scale': 2})
workbook.close()
# Completion message
message_completion = "Done!"
GeneralUtils.show_message(message_completion)

1
_config.yml

@ -0,0 +1 @@
theme: jekyll-theme-cayman

89
dev_notes.md

@ -0,0 +1,89 @@
There are 2 levels of reports, Master Reports (e.g. PR, DR) which show all possible columns and Standard Views (e.g. PR_P1, DR_D1, DR_D2) which only show some of the columns from the master reports.
## Report Fetching
All reports are fetched via the COUNTER_SUSHI API, data is returned as JSON. The JSON models and all other details can be found at: https://app.swaggerhub.com/apis/COUNTER/counter-sushi_5_0_api/1.0.0
### Authentication
SUSHI requests can use these parameters for authentication:
- customer_id (required)
- requestor_id (optional)
- api_key (optional)
There are also other optional parametrs like "platform"
### URL Building
Request supported reports: [base_url]/reports?[authentication],[parameters]
Request report: [base_url]/reports/[report_type]?[authentication],[parameters],[begin_date],[end_date]
## TSV Report Formatting
All information about report formatting can be found at: https://www.projectcounter.org/code-of-practice-five-sections/3-0-technical-specifications/#formats
All reports should be formatted like in this image: https://www.projectcounter.org/wp-content/uploads/2017/07/image3.png
### Report Header
All reports should have a header that takes the first 12 rows of the report. The header should be formatted like in this image: https://www.projectcounter.org/wp-content/uploads/2018/09/FIG-3D.png
A blank row should then be added to separate the report header from the column headings and body of the report.
### Report Column Headings and Body
The column headings for each report type are as follows:
PR
["Platform", "Data_Type", "Access_Method"]
PR_P1
["Platform"]
DR
["Database", "Publisher", "Publisher_ID", "Platform", "Propriety_ID", "Data_Type", "Access_Method"]
DR_D1 and DR_D2
["Database", "Publisher", "Publisher_ID", "Platform", "Propriety_ID"]
TR
["Title", "Publisher", "Publisher_ID", "Platform", "DOI", "Propriety_ID", "ISBN", "Print_ISSN", "Online_ISSN", "Linking_ISSN", "URI", "Data_Type", "Section_Type", "YOP", "Access_Type", "Access_Method"]
TR_B1 and TR_B2
["Title", "Publisher", "Publisher_ID", "Platform", "DOI", "Propriety_ID", "ISBN", "Print_ISSN", "Online_ISSN", "Linking_ISSN", "URI", "YOP"]
TR_B3
["Title", "Publisher", "Publisher_ID", "Platform", "DOI", "Propriety_ID", "ISBN", "Print_ISSN", "Online_ISSN", "Linking_ISSN", "URI", "YOP", "Access_Type"]
TR_J1 and TR_J2
["Title", "Publisher", "Publisher_ID", "Platform", "DOI", "Propriety_ID", "Print_ISSN", "Online_ISSN", "Linking_ISSN", "URI"]
TR_J3
["Title", "Publisher", "Publisher_ID", "Platform", "DOI", "Propriety_ID", "Print_ISSN", "Online_ISSN", "Linking_ISSN", "URI", "Access_Type"]
TR_J4
["Title", "Publisher", "Publisher_ID", "Platform", "DOI", "Propriety_ID", "Print_ISSN", "Online_ISSN", "Linking_ISSN", "URI", "YOP"]
IR
["Item", "Publisher", "Publisher_ID", "Platform", "Authors", "Publication_Date", "Article_version", "DOI", "Propriety_ID", "ISBN", "Print_ISSN", "Online_ISSN", "Linking_ISSN", "URI", "Parent_Title", "Parent_Authors", "Parent_Publication_Date", "Parent_Article_Version", "Parent_Data_Type", "Parent_DOI", "Parent_Proprietary_ID", "Parent_ISBN", "Parent_Print_ISSN", "Parent_Online_ISSN", "Parent_URI", "Data_Type", "YOP", "Access_Type", "Access_Method"]
IR_A1
["Item", "Publisher", "Publisher_ID", "Platform", "Authors", "Publication_Date", "Article_version", "DOI", "Propriety_ID", "Print_ISSN", "Online_ISSN", "Linking_ISSN", "URI", "Parent_Title", "Parent_Authors", "Parent_Article_Version", "Parent_DOI", "Parent_Proprietary_ID", "Parent_Print_ISSN", "Parent_Online_ISSN", "Parent_URI", "Access_Type"]
IR_M1
["Item", "Publisher", "Publisher_ID", "Platform", "DOI", "Propriety_ID", "URI"]
All report types end with these headings:
[
"Metric_Type",
"Reporting_Period_Total",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
]
The report body is then populated with the data received

7
docs/Constants.py.rst

@ -0,0 +1,7 @@
Constants module
========================
.. automodule:: Constants
:members:
:undoc-members:
:show-inheritance:

7
docs/Costs.py.rst

@ -0,0 +1,7 @@
Costs module
============
.. automodule:: Costs
:members:
:undoc-members:
:show-inheritance:

7
docs/FetchData.py.rst

@ -0,0 +1,7 @@
FetchData module
================
.. automodule:: FetchData
:members:
:undoc-members:
:show-inheritance:

7
docs/GeneralUtils.py.rst

@ -0,0 +1,7 @@
GeneralUtils module
===================
.. automodule:: GeneralUtils
:members:
:undoc-members:
:show-inheritance:

7
docs/ImportFile.py.rst

@ -0,0 +1,7 @@
ImportFile module
=================
.. automodule:: ImportFile
:members:
:undoc-members:
:show-inheritance:

7
docs/MainDriver.py.rst

@ -0,0 +1,7 @@
MainDriver module
=================
.. automodule:: MainDriver
:members:
:undoc-members:
:show-inheritance:

20
docs/Makefile

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

7
docs/ManageDB.py.rst

@ -0,0 +1,7 @@
ManageDB module
===============
.. automodule:: ManageDB
:members:
:undoc-members:
:show-inheritance:

7
docs/ManageVendors.py.rst

@ -0,0 +1,7 @@
ManageVendors module
====================
.. automodule:: ManageVendors
:members:
:undoc-members:
:show-inheritance:

7
docs/Search.py.rst

@ -0,0 +1,7 @@
Search module
=============
.. automodule:: Search
:members:
:undoc-members:
:show-inheritance:

7
docs/Settings.py.rst

@ -0,0 +1,7 @@
Settings module
===============
.. automodule:: Settings
:members:
:undoc-members:
:show-inheritance:

7
docs/Visual.py.rst

@ -0,0 +1,7 @@
Visual module
=============
.. automodule:: Visual
:members:
:undoc-members:
:show-inheritance:

58
docs/conf.py

@ -0,0 +1,58 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
# -- Project information -----------------------------------------------------
project = 'COUNTER 5 Report Tool'
copyright = '2020, Adam McGuigan, Chandler Acorn, Samuel Esan, Urvesh Boodhoon, Ziheng Huang'
author = 'Adam McGuigan, Chandler Acorn, Samuel Esan, Urvesh Boodhoon, Ziheng Huang'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx_autodoc_typehints',
'sphinx_rtd_theme'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The master document
master_doc = 'index'
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

31
docs/index.rst

@ -0,0 +1,31 @@
.. COUNTER 5 Report Tool documentation master file, created by
sphinx-quickstart on Sat Mar 21 00:21:37 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to COUNTER 5 Report Tool's documentation!
=================================
.. toctree::
:maxdepth: 2
:caption: Modules:
Constants.py
Costs.py
FetchData.py
GeneralUtils.py
ImportFile.py
MainDriver.py
ManageDB.py
ManageVendors.py
Search.py
Settings.py
Visual.py
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

35
docs/make.bat

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

26
docs/pyinstaller-how-to.md

@ -0,0 +1,26 @@
# How to create COUNTER 5 Report Tool's executable
* Install python
* Install pip
* Install pyinstaller (pip install pyinstaller)
Before starting the process below, make sure to delete your alldata folder as anything included in it will be included in the EXE file.
### Creating the executable in terminal
1. Open terminal/Command Prompt
2. cd to your projectDirectory
3. Run: *pip install -r requirements.txt*
4. Run: *pip show validators*
This will show the validators package location.
5. Run: pyi-makespec --paths=DirectoryWithValidatorsPackage maindriver.py
6. Run pyinstaller
* Windows: Run: pyinstaller --onefile MainDriver.py -n "Counter 5 Report Tool" -i main_icon.ico
* macOS: Run: pyinstaller --onefile --windowed -n "Counter 5 Report Tool" -i main_icon.ico
* UNIX: Run: pyinstaller --onefile MainDriver.py -n "Counter 5 Report Tool" -i main_icon.ico
Check in the project directory, under the folder named dist. There should now be an .exe or .app file. Double click the file to open.
If you receive an error about missing modules make sure that you ran pyi-makespec and gave the right path. If there are other modules other than validators that the exe says it is missing you will need to include their paths as well.

BIN
executables/Linux/Counter 5 Report Tool.zip

Binary file not shown.

BIN
executables/Windows/COUNTER 5 Report Tool.zip

Binary file not shown.

BIN
executables/macOS/Counter 5 Report Tool.zip

Binary file not shown.

BIN
images/CostsHelp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

BIN
images/FetchReportsHelp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

BIN
images/FetchSpecialReportsHelp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

BIN
images/ManageVendorsHelp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

BIN
images/SearchHelp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

BIN
images/SettingsHelp.PNG

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
images/VisualHelp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

BIN
images/importReportsHelp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
main_icon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

13
requirements.txt

@ -0,0 +1,13 @@
certifi==2020.4.5.1
chardet==3.0.4
decorator==4.4.2
idna==2.9
PyQt5==5.12.3
PyQt5-sip==12.7.2
requests==2.23.0
six==1.14.0
urllib3==1.25.9
validators==0.14.3
XlsxWriter==1.2.8
sphinx==2.4.4
sphinx_autodoc_typehints

0
tests/data/test_file_for_import.tsv

34
tests/test_AddVendorDialog.py

@ -0,0 +1,34 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication, QDialog
from ui import AddVendorDialog
app = QApplication(sys.argv)
vendor_dialog = QDialog()
vendor_dialog_ui = AddVendorDialog.Ui_addVendorDialog()
vendor_dialog_ui.setupUi(vendor_dialog)
class AddVendorDialogTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(vendor_dialog_ui.nameEdit.text(), "")
self.assertEqual(vendor_dialog_ui.customerIdEdit.text(), "")
self.assertEqual(vendor_dialog_ui.baseUrlEdit.text(), "")
self.assertEqual(vendor_dialog_ui.requestorIdEdit.text(), "")
self.assertEqual(vendor_dialog_ui.apiKeyEdit.text(), "")
self.assertEqual(vendor_dialog_ui.platformEdit.text(), "")
self.assertEqual(vendor_dialog_ui.local_only_check_box.checkState(), False)
self.assertEqual(vendor_dialog_ui.descriptionEdit.toPlainText(), "")
def test_ok_button(self):
okWidget = vendor_dialog_ui.buttonBox.Ok
self.assertIsNotNone(okWidget)
cancelWidget = vendor_dialog_ui.buttonBox.Cancel
self.assertIsNotNone(cancelWidget)
if __name__ == "__main__":
unittest.main()

53
tests/test_CostsTab.py

@ -0,0 +1,53 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import CostsTab
app = QApplication(sys.argv)
costTab_widget = QWidget()
costTab_widget_ui = CostsTab.Ui_costs_tab()
costTab_widget_ui.setupUi(costTab_widget)
class CostsTabTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(costTab_widget_ui.costs_name_parameter_label.text(),"Name")
self.assertEqual(costTab_widget_ui.costs_report_parameter_label.text(), "Report")
self.assertEqual(costTab_widget_ui.costs_vendor_parameter_label.text(),"Vendor")
self.assertEqual(costTab_widget_ui.costs_year_parameter_label.text(),"Year")
self.assertEqual(costTab_widget_ui.costs_cost_in_local_currency_label.text(),"Cost in Local Currency")
self.assertEqual(costTab_widget_ui.costs_cost_in_local_currency_with_tax_label.text(),"Cost in Local Currency with Tax")
self.assertEqual(costTab_widget_ui.costs_cost_in_original_currency_label.text(),"Cost in Original Currency")
self.assertEqual(costTab_widget_ui.costs_original_currency_label.text(),"Original Currency")
def test_doublesPinBox(self):
'''Test the defaults'''
self.assertEqual(costTab_widget_ui.costs_cost_in_local_currency_doublespinbox.text(),"")
self.assertEqual(costTab_widget_ui.costs_cost_in_local_currency_with_tax_doublespinbox.text(),"")
self.assertEqual(costTab_widget_ui.costs_cost_in_original_currency_doublespinbox.text(),"")
def test_combobox(self):
'''Test the defaults'''
self.assertEqual(costTab_widget_ui.costs_name_parameter_combobox.isEditable(),True)
self.assertEqual(costTab_widget_ui.costs_report_parameter_combobox.isEditable(),False)
self.assertEqual(costTab_widget_ui.costs_vendor_parameter_combobox.isEditable(),False)
self.assertEqual(costTab_widget_ui.costs_original_currency_value_combobox.isEditable(),True)
self.assertEqual(costTab_widget_ui.costs_name_parameter_combobox.currentText(), "")
self.assertEqual(costTab_widget_ui.costs_report_parameter_combobox.currentText(), "")
self.assertEqual(costTab_widget_ui.costs_vendor_parameter_combobox.currentText(), "")
self.assertEqual(costTab_widget_ui.costs_original_currency_value_combobox.currentText(), "")
def test_dateEdit(self):
'''Test the defaults'''
self.assertEqual(costTab_widget_ui.costs_year_parameter_dateedit.text(),"2000")
def test_button(self):
'''Test the defaults'''
self.assertEqual(costTab_widget_ui.costs_clear_button.text(), "Clear")
self.assertEqual(costTab_widget_ui.costs_insert_button.text(), "Insert")
self.assertEqual(costTab_widget_ui.costs_load_button.text(), "Load")
self.assertEqual(costTab_widget_ui.costs_load_from_disk_button.text(), "Load From Disk")
if __name__ == '__main__':
unittest.main()

22
tests/test_DisclaimerDialog.py

@ -0,0 +1,22 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QDialog
from ui import DisclaimerDialog
app = QApplication(sys.argv)
disclaimer_dialog = QDialog()
disclaimer_dialog_ui = DisclaimerDialog.Ui_dialog()
disclaimer_dialog_ui.setupUi(disclaimer_dialog)
class DisclaimerDialogTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(disclaimer_dialog_ui.label.text(),"Only reports supported by selected vendor will be retrieved!")
def test_button(self):
okWidget = disclaimer_dialog_ui.buttonBox.Ok
self.assertIsNotNone(okWidget)
if __name__ == '__main__':
unittest.main()

28
tests/test_FetchProgressDialog.py

@ -0,0 +1,28 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QDialog
from ui import FetchProgressDialog
app = QApplication(sys.argv)
fetch_progress_dialog = QDialog()
fetch_progress_dialog_ui = FetchProgressDialog.Ui_FetchProgressDialog()
fetch_progress_dialog_ui.setupUi(fetch_progress_dialog)
class FetchProgressDialogTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(fetch_progress_dialog_ui.status_label.text(), "Fetching...")
self.assertEqual(fetch_progress_dialog_ui.progress_bar.text(), "24%")
def test_button(self):
okWidget = fetch_progress_dialog_ui.buttonBox.Ok
self.assertIsNotNone(okWidget)
retryWidget = fetch_progress_dialog_ui.buttonBox.Retry
self.assertIsNotNone(retryWidget)
cancelWidget = fetch_progress_dialog_ui.buttonBox.Cancel
self.assertIsNotNone(cancelWidget)
if __name__ == '__main__':
unittest.main()

50
tests/test_FetchReportsTab.py

@ -0,0 +1,50 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import FetchReportsTab
app = QApplication(sys.argv)
fetchReportsTab_widget = QWidget()
fetchReportsTab_widget_ui = FetchReportsTab.Ui_fetch_reports_tab()
fetchReportsTab_widget_ui.setupUi(fetchReportsTab_widget)
class FetchReportsTabTest(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(fetchReportsTab_widget_ui.Adv_Fetch_text.text(),"Advanced Fetch Reports")
self.assertEqual(fetchReportsTab_widget_ui.label_11.text(),"Select Vendors")
self.assertEqual(fetchReportsTab_widget_ui.label_12.text(), "Select Report Types")
self.assertEqual(fetchReportsTab_widget_ui.label_38.text(), "Not a yearly date range")
self.assertEqual(fetchReportsTab_widget_ui.label_41.text(), "Report(s) will be saved to:")
self.assertEqual(fetchReportsTab_widget_ui.label_10.text(), "End Date")
self.assertEqual(fetchReportsTab_widget_ui.label_9.text(), "Begin Date")
self.assertEqual(fetchReportsTab_widget_ui.label_8.text(), "Date Range")
self.assertEqual(fetchReportsTab_widget_ui.label_34.text(), "Year")
self.assertEqual(fetchReportsTab_widget_ui.label_35.text(), "Fetch All Reports")
def test_dateEdit(self):
'''Test the defaults'''
self.assertEqual(fetchReportsTab_widget_ui.begin_date_edit_fetch_month.text(),"01")
self.assertEqual(fetchReportsTab_widget_ui.begin_date_edit_fetch_year.text(),"2020")
self.assertEqual(fetchReportsTab_widget_ui.end_date_edit_fetch_month.text(),"01")
self.assertEqual(fetchReportsTab_widget_ui.end_date_edit_fetch_year.text(),"2020")
self.assertEqual(fetchReportsTab_widget_ui.All_reports_edit_fetch.text(),"2020")
def test_pushButton(self):
'''Test the defaults'''
self.assertEqual(fetchReportsTab_widget_ui.deselect_vendors_button_fetch.text(),"Deselect All")
self.assertEqual(fetchReportsTab_widget_ui.select_vendors_button_fetch.text(),"Select All")
self.assertEqual(fetchReportsTab_widget_ui.deselect_report_types_button_fetch.text(), "Deselect All")
self.assertEqual(fetchReportsTab_widget_ui.select_report_types_button_fetch.text(), "Select All")
self.assertEqual(fetchReportsTab_widget_ui.report_types_help_button.text(),"?")
self.assertEqual(fetchReportsTab_widget_ui.fetch_advanced_button.text(),"Fetch Selected Reports")
self.assertEqual(fetchReportsTab_widget_ui.custom_dir_button.text(),"Change")
self.assertEqual(fetchReportsTab_widget_ui.fetch_all_data_button.text(),"Fetch All Reports")
def test_lineEdit(self):
'''Test the defaults'''
self.assertEqual(fetchReportsTab_widget_ui.custom_dir_edit.text(),"")
if __name__ == '__main__':
unittest.main()

43
tests/test_FetchSpecialReportsTab.py

@ -0,0 +1,43 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import FetchSpecialReportsTab
app = QApplication(sys.argv)
fetchSpecialReportsTab_widget = QWidget()
fetchSpecialReportsTab_widget_ui = FetchSpecialReportsTab.Ui_fetch_special_reports_tab()
fetchSpecialReportsTab_widget_ui.setupUi(fetchSpecialReportsTab_widget)
class FetchSpecialReportsTabTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(fetchSpecialReportsTab_widget_ui.label_20.text(),"Select Report Type")
self.assertEqual(fetchSpecialReportsTab_widget_ui.label_21.text(), "Select Vendors")
self.assertEqual(fetchSpecialReportsTab_widget_ui.label_14.text(),"Options")
self.assertEqual(fetchSpecialReportsTab_widget_ui.label_25.text(),"End Date")
self.assertEqual(fetchSpecialReportsTab_widget_ui.label_24.text(),"Begin Date")
self.assertEqual(fetchSpecialReportsTab_widget_ui.label_15.text(),"Date Range")
def test_radioButrton(self):
'''Test the defaults'''
self.assertEqual(fetchSpecialReportsTab_widget_ui.dr_radio_button.text(),"DR")
self.assertEqual(fetchSpecialReportsTab_widget_ui.pr_radio_button.text(), "PR")
self.assertEqual(fetchSpecialReportsTab_widget_ui.tr_radio_button.text(), "TR")
self.assertEqual(fetchSpecialReportsTab_widget_ui.ir_radio_button.text(), "IR")
def test_pushButton(self):
'''Test the defaults'''
self.assertEqual(fetchSpecialReportsTab_widget_ui.deselect_vendors_button_special.text(),"Deselect All")
self.assertEqual(fetchSpecialReportsTab_widget_ui.select_vendors_button_special.text(),"Select All")
self.assertEqual(fetchSpecialReportsTab_widget_ui.fetch_special_data_button.text(),"Fetch Special Report")
def test_dateEdit(self):
'''Test the defaults'''
self.assertEqual(fetchSpecialReportsTab_widget_ui.begin_date_edit_special_month.text(),"01")
self.assertEqual(fetchSpecialReportsTab_widget_ui.begin_date_edit_special_year.text(),"2020")
self.assertEqual(fetchSpecialReportsTab_widget_ui.end_date_edit_special_month.text(),"01")
self.assertEqual(fetchSpecialReportsTab_widget_ui.end_date_edit_special_year.text(),"2020")
if __name__ == '__main__':
unittest.main()

184
tests/test_ImportFile.py

@ -0,0 +1,184 @@
import sys
import pytest
from os import path
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import QDate
from PyQt5.QtGui import QStandardItemModel
from ui import MainWindow
from ImportFile import ImportReportController
from ManageVendors import Vendor
from FetchData import ALL_REPORTS, CompletionStatus
import Settings
import GeneralUtils
import json
@pytest.fixture(scope='session')
def qapp_args():
return sys.argv
@pytest.fixture(scope='session')
def vendors() -> list:
assert path.exists("./data/vendor_manager/vendors.dat"), \
"test vendor.dat should be placed in ./tests/data/vendor_manager/"
vendor_list = []
vendors_json_string = GeneralUtils.read_json_file("./data/vendor_manager/vendors.dat")
vendor_dicts = json.loads(vendors_json_string)
for json_dict in vendor_dicts:
vendor = Vendor.from_json(json_dict)
vendor_list.append(vendor)
return vendor_list
@pytest.fixture(scope='session')
def settings() -> Settings.SettingsModel:
return Settings.SettingsModel(Settings.YEARLY_DIR,
Settings.OTHER_DIR,
Settings.REQUEST_INTERVAL,
Settings.REQUEST_TIMEOUT,
Settings.CONCURRENT_VENDORS,
Settings.CONCURRENT_REPORTS,
Settings.EMPTY_CELL,
Settings.USER_AGENT)
@pytest.fixture
def controller(qtbot, settings): # ImportFileController without populated vendor list
window = QMainWindow()
window_ui = MainWindow.Ui_mainWindow()
window_ui.setupUi(window)
c = ImportReportController([], settings, window_ui)
yield c
@pytest.fixture
def controller_v(qtbot, vendors, settings): # ImportFileController with populated vendor list
window = QMainWindow()
window_ui = MainWindow.Ui_mainWindow()
window_ui.setupUi(window)
c = ImportReportController(vendors, settings, window_ui)
yield c
def test_on_vendors_changed(controller, vendors):
controller.on_vendors_changed(vendors)
assert controller.selected_vendor_index == -1
assert len(controller.vendors) == len(vendors)
assert controller.vendor_list_model.rowCount() == len(vendors)
def test_update_vendors(controller, vendors):
controller.update_vendors(vendors)
assert len(controller.vendors) == len(vendors)
for i in range(len(controller.vendors)):
assert controller.vendors[i].name == vendors[i].name
def test_update_vendors_ui(controller, vendors):
controller.update_vendors(vendors)
vendor_list_model = controller.vendor_list_model
assert vendor_list_model.rowCount() == 0
controller.update_vendors_ui()
assert vendor_list_model.rowCount() == len(controller.vendors)
for i in range(len(controller.vendors)):
assert vendor_list_model.item(i, 0).text() == controller.vendors[i].name
def test_on_vendor_selected(controller_v, vendors, settings):
index_to_select = 5
model_index = QStandardItemModel.createIndex(QStandardItemModel(), index_to_select, 0)
controller_v.on_vendor_selected(model_index)
assert controller_v.selected_vendor_index == index_to_select
def test_on_report_type_selected(controller_v):
index_to_select = 3
model_index = QStandardItemModel.createIndex(QStandardItemModel(), index_to_select, 0)
controller_v.on_report_type_selected(model_index)
assert controller_v.selected_report_type_index == index_to_select
def test_on_date_changed(controller_v):
test_date = QDate.currentDate()
controller_v.on_date_changed(test_date)
assert controller_v.date == test_date
def test_on_import_clicked(controller_v):
# No vendor selected
controller_v.on_import_clicked()
controller_v.selected_vendor_index = 1
# No report type selected
controller_v.on_import_clicked()
controller_v.selected_report_type_index = 1
vendor = controller_v.vendors[controller_v.selected_vendor_index]
report_type = ALL_REPORTS[controller_v.selected_report_type_index]
file_dir = f"{controller_v.settings.yearly_directory}{controller_v.date.toString('yyyy')}/{vendor.name}/"
file_name = f"{controller_v.date.toString('yyyy')}_{vendor.name}_{report_type}.tsv"
file_path = file_dir + file_name
# No file selected
controller_v.on_import_clicked()
# Invalid file selected
controller_v.selected_file_path = "./data/invalid_file"
controller_v.on_import_clicked()
# Valid file selected
controller_v.selected_file_path = "./data/test_file_for_import.tsv"
controller_v.on_import_clicked()
assert path.isfile(file_path)
def test_import_file(controller_v):
controller_v.selected_vendor_index = 1
controller_v.selected_report_type_index = 1
vendor = controller_v.vendors[controller_v.selected_vendor_index]
report_type = ALL_REPORTS[controller_v.selected_report_type_index]
file_dir = f"{controller_v.settings.yearly_directory}{controller_v.date.toString('yyyy')}/{vendor.name}/"
file_name = f"{controller_v.date.toString('yyyy')}_{vendor.name}_{report_type}.tsv"
file_path = file_dir + file_name
# No file selected
assert controller_v.import_report(vendor, report_type).completion_status == CompletionStatus.FAILED
# Invalid file selected
controller_v.selected_file_path = "./data/invalid_file"
assert controller_v.import_report(vendor, report_type).completion_status == CompletionStatus.FAILED
# Valid file selected
controller_v.selected_file_path = "./data/test_file_for_import.tsv"
assert controller_v.import_report(vendor, report_type).completion_status == CompletionStatus.SUCCESSFUL
assert path.isfile(file_path)
def test_open_file(controller_v):
# Invalid file/folder
controller_v.open_explorer("./data/invalid_file")
# Valid file
controller_v.open_explorer("./data/test_file_for_import.tsv")
# Valid folder
controller_v.open_explorer("./data/")

35
tests/test_ImportReportTab.py

@ -0,0 +1,35 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import ImportReportTab
app = QApplication(sys.argv)
importReportTab_widget = QWidget()
importReportTab_widget_ui = ImportReportTab.Ui_import_report_tab()
importReportTab_widget_ui.setupUi(importReportTab_widget)
class ImportReportTabTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(importReportTab_widget_ui.label_17.text(),"Select Report Type")
self.assertEqual(importReportTab_widget_ui.label_18.text(),"Select Vendor")
self.assertEqual(importReportTab_widget_ui.label_19.text(),"Report Year")
self.assertEqual(importReportTab_widget_ui.label_16.text(), "Date")
self.assertEqual(importReportTab_widget_ui.label_36.text(),"Target Report File")
def test_dateEdit(self):
'''Test the defaults'''
self.assertEqual(importReportTab_widget_ui.report_year_date_edit.text(),"2000")
def test_pushButton(self):
'''Test the defaults'''
self.assertEqual(importReportTab_widget_ui.select_file_button.text(),"Select File")
self.assertEqual(importReportTab_widget_ui.import_report_button.text(),"Import Selected Report")
def test_lineEdit(self):
'''Test the defaults'''
self.assertEqual(importReportTab_widget_ui.selected_file_edit.text(),"")
if __name__ == '__main__':
unittest.main()

160
tests/test_MainWindow.py

@ -0,0 +1,160 @@
import sys
import unittest
from PyQt5.QtWidgets import QApplication, QMainWindow
from ui import MainWindow
app = QApplication(sys.argv)
main_window = QMainWindow()
main_window_ui = MainWindow.Ui_mainWindow()
main_window_ui.setupUi(main_window)
class MyTestCase(unittest.TestCase):
def test_addVendorButton(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.addVendorButton.text(), "Add New Vendor")
def test_edit_vendor_options_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.removeVendorButton.text(), "Remove Vendor")
self.assertEqual(main_window_ui.saveVendorChangesButton.text(), "Save Changes")
self.assertEqual(main_window_ui.undoVendorChangesButton.text(), "Undo Changes")
def test_select_vendor_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.deselect_vendors_button_fetch.text(), "Deselect All")
self.assertEqual(main_window_ui.select_vendors_button_fetch.text(), "Select All")
self.assertEqual(main_window_ui.deselect_vendors_button_special.text(), "Deselect All")
self.assertEqual(main_window_ui.select_vendors_button_special.text(), "Select All")
def test_select_report_types_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.deselect_report_types_button_fetch.text(), "Deselect All")
self.assertEqual(main_window_ui.select_report_types_button_fetch.text(), "Select All")
self.assertEqual(main_window_ui.toolButton.text(), "?")
def test_fetch_advanced_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.fetch_advanced_button.text(), "Fetch Selected Reports")
def test_fetch_all_data_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.fetch_all_data_button.text(), "Fetch All Reports")
def test_fetch_speical_data_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.fetch_special_data_button.text(), "Fetch Special Report")
def test_select_file_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.select_file_button.text(), "Select File")
self.assertEqual(main_window_ui.import_file_button.text(), "Import Selected File")
def test_search_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.search_button.text(), "Search")
def test_setting_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.concurrent_reports_help_button.text(), "?")
self.assertEqual(main_window_ui.concurrent_vendors_help_button.text(), "?")
self.assertEqual(main_window_ui.empty_cell_help_button.text(), "?")
self.assertEqual(main_window_ui.other_directory_button.text(), "Choose Folder...")
self.assertEqual(main_window_ui.other_directory_help_button.text(), "?")
self.assertEqual(main_window_ui.request_interval_help_button.text(), "?")
self.assertEqual(main_window_ui.request_timeout_help_button.text(), "?")
self.assertEqual(main_window_ui.yearly_directory_button.text(), "Choose Folder...")
self.assertEqual(main_window_ui.yearly_directory_help_button.text(), "?")
def test_setting_spin_box(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.concurrent_reports_spin_box.value(),0)
self.assertEqual(main_window_ui.concurrent_vendors_spin_box.value(), 0)
self.assertEqual(main_window_ui.request_interval_spin_box.value(), 0)
self.assertEqual(main_window_ui.request_timeout_spin_box.value(), 0)
def test_date_edit(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.begin_date_edit_fetch.text(), "2020-01")
self.assertEqual(main_window_ui.end_date_edit_fetch.text(), "2020-01")
self.assertEqual(main_window_ui.All_reports_edit_fetch.text(), "2020")
self.assertEqual(main_window_ui.begin_date_edit_special.text(), "2000-01")
self.assertEqual(main_window_ui.end_date_edit_special.text(), "2000-01")
self.assertEqual(main_window_ui.report_year_date_edit.text(), "2000")
def test_radio_button(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.dr_radio_button.isChecked(), False)
self.assertEqual(main_window_ui.ir_radio_button.isChecked(), False)
self.assertEqual(main_window_ui.tr_radio_button.isChecked(), False)
self.assertEqual(main_window_ui.pr_radio_button.isChecked(), True)
def test_label(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.label.text(), "Name")
self.assertEqual(main_window_ui.label_2.text(), "Customer ID")
self.assertEqual(main_window_ui.label_3.text(), "Base URL")
self.assertEqual(main_window_ui.label_4.text(), "Requestor ID")
self.assertEqual(main_window_ui.label_5.text(), "API Key")
self.assertEqual(main_window_ui.label_6.text(), "Platform")
self.assertEqual(main_window_ui.label_7.text(), "Edit Vendor")
self.assertEqual(main_window_ui.label_9.text(), "Begin Date")
self.assertEqual(main_window_ui.label_10.text(), "End Date")
self.assertEqual(main_window_ui.label_11.text(), "Select Vendors")
self.assertEqual(main_window_ui.label_12.text(), "Select Report Types")
self.assertEqual(main_window_ui.label_13.text(), "Select Vendor")
self.assertEqual(main_window_ui.label_14.text(), "Search Keyword(s)")
self.assertEqual(main_window_ui.label_15.text(), "Search Results")
self.assertEqual(main_window_ui.label_16.text(), "Search by:")
self.assertEqual(main_window_ui.label_17.text(), "Select Report Type")
self.assertEqual(main_window_ui.label_18.text(), "Select Vendor")
self.assertEqual(main_window_ui.label_19.text(), "Report Year")
self.assertEqual(main_window_ui.label_20.text(), "Select Report Type")
self.assertEqual(main_window_ui.label_21.text(), "Select Vendors")
self.assertEqual(main_window_ui.label_22.text(), "Begin Date")
self.assertEqual(main_window_ui.label_23.text(), "End Date")
self.assertEqual(main_window_ui.label_24.text(), "Reports")
self.assertEqual(main_window_ui.label_25.text(), "Yearly Reports Directory")
self.assertEqual(main_window_ui.label_26.text(), "Search")
self.assertEqual(main_window_ui.label_28.text(), "Description")
self.assertEqual(main_window_ui.label_29.text(), "Other Reports Directory")
self.assertEqual(main_window_ui.label_30.text(), "Report Request Interval")
self.assertEqual(main_window_ui.label_31.text(), "Concurrent Vendors")
self.assertEqual(main_window_ui.label_32.text(), "Concurrent Reports")
self.assertEqual(main_window_ui.label_33.text(), "Empty Cell")
self.assertEqual(main_window_ui.label_34.text(), "Year")
self.assertEqual(main_window_ui.label_35.text(), "Fetch All Reports")
self.assertEqual(main_window_ui.label_37.text(), "Request Timeout")
self.assertEqual(main_window_ui.label_39.text(), "Local Only Vendor")
self.assertEqual(main_window_ui.Adv_Fetch_text.text(), "Advanced Fetch Reports")
self.assertEqual(main_window_ui.selected_file_label.text(), "None")
def test_check_box(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.local_only_check_box.checkState(), False)
self.assertEqual(main_window_ui.isbn_checkbox.checkState(), False)
self.assertEqual(main_window_ui.issn_checkbox.checkState(), False)
self.assertEqual(main_window_ui.title_checkbox.checkState(), False)
def test_line_edit(self):
'''Test the defaults'''
self.assertEqual(main_window_ui.apiKeyEdit.text(),"")
self.assertEqual(main_window_ui.baseUrlEdit.text(), "")
self.assertEqual(main_window_ui.customerIdEdit.text(), "")
self.assertEqual(main_window_ui.descriptionEdit.toPlainText(), "")
self.assertEqual(main_window_ui.nameEdit.text(), "")
self.assertEqual(main_window_ui.platformEdit.text(), "")
self.assertEqual(main_window_ui.requestorIdEdit.text(), "")
self.assertEqual(main_window_ui.search_term_edit.text(), "")
self.assertEqual(main_window_ui.other_directory_edit.text(), "")
self.assertEqual(main_window_ui.yearly_directory_edit.text(), "")
self.assertEqual(main_window_ui.empty_cell_edit.text(), "")
self.assertEqual(main_window_ui.save_location_edit_fetch_2.text(), "[In Development]")
if __name__ == '__main__':
unittest.main()

53
tests/test_ManageVendorsTab.py

@ -0,0 +1,53 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import ManageVendorsTab
app = QApplication(sys.argv)
manageVendorsTab_widget = QWidget()
manageVendorsTab_widget_ui = ManageVendorsTab.Ui_manage_vendors_tab()
manageVendorsTab_widget_ui.setupUi(manageVendorsTab_widget)
class ManageVendorsTabTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(manageVendorsTab_widget_ui.label_13.text(),"Select Vendor")
self.assertEqual(manageVendorsTab_widget_ui.companiesText.text(),"External Companies")
self.assertEqual(manageVendorsTab_widget_ui.label.text(),"Name")
self.assertEqual(manageVendorsTab_widget_ui.label_2.text(),"Customer ID")
self.assertEqual(manageVendorsTab_widget_ui.label_28.text(), "Description")
self.assertEqual(manageVendorsTab_widget_ui.label_3.text(),"Base URL")
self.assertEqual(manageVendorsTab_widget_ui.label_39.text(), "Local Only Vendor")
self.assertEqual(manageVendorsTab_widget_ui.label_4.text(),"Requestor ID")
self.assertEqual(manageVendorsTab_widget_ui.label_5.text(), "API Key")
self.assertEqual(manageVendorsTab_widget_ui.label_6.text(), "Platform")
self.assertEqual(manageVendorsTab_widget_ui.name_validation_label.text(),"Validation label")
self.assertEqual(manageVendorsTab_widget_ui.url_validation_label.text(),"Validation label")
def test_pushButton(self):
'''Test the defaults'''
self.assertEqual(manageVendorsTab_widget_ui.addVendorButton.text(),"Add New Vendor")
self.assertEqual(manageVendorsTab_widget_ui.exportVendorsButton.text(),"Export Vendors")
self.assertEqual(manageVendorsTab_widget_ui.importVendorsButton.text(),"Import Vendors")
self.assertEqual(manageVendorsTab_widget_ui.removeVendorButton.text(), "Remove Vendor")
self.assertEqual(manageVendorsTab_widget_ui.saveVendorChangesButton.text(), "Save Changes")
self.assertEqual(manageVendorsTab_widget_ui.undoVendorChangesButton.text(), "Undo Changes")
def test_lineEdit(self):
'''Test the defaults'''
self.assertEqual(manageVendorsTab_widget_ui.apiKeyEdit.text(),"")
self.assertEqual(manageVendorsTab_widget_ui.baseUrlEdit.text(), "")
self.assertEqual(manageVendorsTab_widget_ui.companiesEdit.toPlainText(), "")
self.assertEqual(manageVendorsTab_widget_ui.customerIdEdit.text(), "")
self.assertEqual(manageVendorsTab_widget_ui.descriptionEdit.toPlainText(), "")
self.assertEqual(manageVendorsTab_widget_ui.nameEdit.text(), "")
self.assertEqual(manageVendorsTab_widget_ui.platformEdit.text(), "")
self.assertEqual(manageVendorsTab_widget_ui.requestorIdEdit.text(), "")
def test_checkBox(self):
'''Test the defaults'''
self.assertEqual(manageVendorsTab_widget_ui.local_only_check_box.isChecked(),False)
if __name__ == '__main__':
unittest.main()

22
tests/test_MessageDialog.py

@ -0,0 +1,22 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QDialog
from ui import MessageDialog
app = QApplication(sys.argv)
message_dialog = QDialog()
message_dialog_ui = MessageDialog.Ui_message_dialog()
message_dialog_ui.setupUi(message_dialog)
class MessageDialogTest(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(message_dialog_ui.message_label.text(),"Message!")
def test_button(self):
okWidget = message_dialog_ui.buttonBox.Ok
self.assertIsNotNone(okWidget)
if __name__ == '__main__':
unittest.main()

23
tests/test_RemoveVendorDialog.py

@ -0,0 +1,23 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QDialog
from ui import RemoveVendorDialog
app = QApplication(sys.argv)
remove_vendor_dialog = QDialog()
remove_vendor_dialog_ui = RemoveVendorDialog.Ui_dialog_remove()
remove_vendor_dialog_ui.setupUi(remove_vendor_dialog)
class RemoveVendorDialogTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(remove_vendor_dialog_ui.label.text(),
"Are you sure you want to remove this vendor?")
def test_button(self):
okWidget = remove_vendor_dialog_ui.buttonBox.Ok
self.assertIsNotNone(okWidget)
if __name__ == '__main__':
unittest.main()

28
tests/test_ReportResultWidget.py

@ -0,0 +1,28 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import ReportResultWidget
app = QApplication(sys.argv)
report_result_widget = QWidget()
report_result_ui = ReportResultWidget.Ui_ReportResultWidget()
report_result_ui.setupUi(report_result_widget)
class ReportResultWidgetTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(report_result_ui.file_label.text(),"Saved as: Bleh.tsv")
self.assertEqual(report_result_ui.message_label.text(),"No exception messages")
self.assertEqual(report_result_ui.label_6.text(),"Retry")
self.assertEqual(report_result_ui.success_label.text(),"Failed!")
self.assertEqual(report_result_ui.report_type_label.text(),"TR_J1")
def test_button(self):
self.assertEqual(report_result_ui.folder_button.text(),"")
def test_checkBox(self):
self.assertEqual(report_result_ui.retry_check_box.checkState(),False)
if __name__ == '__main__':
unittest.main()

26
tests/test_ReportTypeDialog.py

@ -0,0 +1,26 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QDialog
from ui import ReportTypeDialog
app = QApplication(sys.argv)
report_type_dialog = QDialog()
report_type_dialog_ui = ReportTypeDialog.Ui_report_type_dialog()
report_type_dialog_ui.setupUi(report_type_dialog)
class ReportTypeDialogTests(unittest.TestCase):
def test_comboBox(self):
'''Test the defaults'''
self.assertEqual(report_type_dialog_ui.report_type_combobox.isEditable(),False)
self.assertEqual(report_type_dialog_ui.report_type_combobox.currentText(),"")
def test_buttonBox(self):
'''Test the defaults'''
okWidget = report_type_dialog_ui.buttonBox.Ok
self.assertIsNotNone(okWidget)
cancelWidget = report_type_dialog_ui.buttonBox.Cancel
self.assertIsNotNone(cancelWidget)
if __name__ == '__main__':
unittest.main()

19
tests/test_SearchAndFrame.py

@ -0,0 +1,19 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QFrame
from ui import SearchAndFrame
app = QApplication(sys.argv)
search_and_clause_frame = QFrame()
search_and_clause_frame_ui = SearchAndFrame.Ui_search_and_clause_parameter_frame()
search_and_clause_frame_ui.setupUi(search_and_clause_frame)
class SearchAndClauseFrameTests(unittest.TestCase):
def test_button(self):
self.assertEqual(search_and_clause_frame_ui.search_add_or_clause_button.text(),"Add \"Or\" Clause")
self.assertEqual(search_and_clause_frame_ui.search_remove_and_clause_button.text(),"Remove \"And\" Clause")
if __name__ == '__main__':
unittest.main()

26
tests/test_SearchOrFrame.py

@ -0,0 +1,26 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QFrame
from ui import SearchOrFrame
app = QApplication(sys.argv)
search_or_clause_frame = QFrame()
search_or_clause_frame_ui = SearchOrFrame.Ui_search_or_clause_parameter_frame()
search_or_clause_frame_ui.setupUi(search_or_clause_frame)
class SearchOrClauseFrameTests(unittest.TestCase):
def test_button(self):
self.assertEqual(search_or_clause_frame_ui.search_remove_or_clause_button.text(),"Remove \"Or\" Clause")
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(search_or_clause_frame_ui.search_value_parameter_lineedit.text(), "")
def test_combo_box(self):
self.assertEqual(search_or_clause_frame_ui.search_comparison_parameter_combobox.currentText(),"")
self.assertEqual(search_or_clause_frame_ui.search_field_parameter_combobox.currentText(),"")
if __name__ == '__main__':
unittest.main()

44
tests/test_SearchTab.py

@ -0,0 +1,44 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import SearchTab
app = QApplication(sys.argv)
searchTab_widget = QWidget()
searchTab_widget_ui = SearchTab.Ui_search_tab()
searchTab_widget_ui.setupUi(searchTab_widget)
class SearchTabTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(searchTab_widget_ui.search_end_year_parameter_label.text(),"End year")
def test_radioButton(self):
'''Test the defaults'''
self.assertEqual(searchTab_widget_ui.dont_open_radioButton.text(),"Don't Open")
self.assertEqual(searchTab_widget_ui.open_both_radioButton.text(), "Open Both")
self.assertEqual(searchTab_widget_ui.open_file_radioButton.text(), "Open File")
self.assertEqual(searchTab_widget_ui.open_folder_radioButton.text(), "Open Folder")
self.assertEqual(searchTab_widget_ui.search_report_parameter_label.text(),"Report")
self.assertEqual(searchTab_widget_ui.search_start_year_parameter_label.text(),"Start Year")
def test_pushButton(self):
'''Test the defaults'''
self.assertEqual(searchTab_widget_ui.search_button.text(),"Search")
self.assertEqual(searchTab_widget_ui.search_export_button.text(),"Export Search")
self.assertEqual(searchTab_widget_ui.search_import_button.text(),"Import Search")
self.assertEqual(searchTab_widget_ui.search_add_and_button.text(),"Add \"And\" Clause")
def test_dateEdit(self):
'''Test the defaults'''
self.assertEqual(searchTab_widget_ui.search_end_year_parameter_dateedit.text(),"2000")
self.assertEqual(searchTab_widget_ui.search_start_year_parameter_dateedit.text(),"2000")
def test_comboBox(self):
'''Test the defaults'''
self.assertEqual(searchTab_widget_ui.search_report_parameter_combobox.isEditable(), False)
self.assertEqual(searchTab_widget_ui.search_report_parameter_combobox.currentText(), "")
if __name__ == '__main__':
unittest.main()

56
tests/test_SettingTab.py

@ -0,0 +1,56 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import SettingsTab
app = QApplication(sys.argv)
settingsTab_widget = QWidget()
settingsTab_widget_ui = SettingsTab.Ui_settings_tab()
settingsTab_widget_ui.setupUi(settingsTab_widget)
class SettingsTabTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(settingsTab_widget_ui.label_25.text(), "Yearly Reports Directory")
self.assertEqual(settingsTab_widget_ui.label_29.text(),"Other Reports Directory")
self.assertEqual(settingsTab_widget_ui.label_30.text(), "Report Request Interval")
self.assertEqual(settingsTab_widget_ui.label_31.text(), "Concurrent Vendors")
self.assertEqual(settingsTab_widget_ui.label_32.text(), "Concurrent Reports")
self.assertEqual(settingsTab_widget_ui.label_33.text(), "Empty Cell")
self.assertEqual(settingsTab_widget_ui.label_37.text(), "Request Timeout")
self.assertEqual(settingsTab_widget_ui.label_73.text(), "User Agent")
self.assertEqual(settingsTab_widget_ui.label_24.text(),"Reports")
self.assertEqual(settingsTab_widget_ui.label_26.text(),"Search")
def test_pushButton(self):
'''Test the defaults'''
self.assertEqual(settingsTab_widget_ui.save_button.text(),"Save Changes")
self.assertEqual(settingsTab_widget_ui.concurrent_reports_help_button.text(),"?")
self.assertEqual(settingsTab_widget_ui.concurrent_vendors_help_button.text(), "?")
self.assertEqual(settingsTab_widget_ui.empty_cell_help_button.text(), "?")
self.assertEqual(settingsTab_widget_ui.other_directory_help_button.text(), "?")
self.assertEqual(settingsTab_widget_ui.request_interval_help_button.text(), "?")
self.assertEqual(settingsTab_widget_ui.request_timeout_help_button.text(), "?")
self.assertEqual(settingsTab_widget_ui.other_directory_button.text(),"Choose")
self.assertEqual(settingsTab_widget_ui.yearly_directory_button.text(), "Choose")
self.assertEqual(settingsTab_widget_ui.user_agent_help_button.text(), "?")
self.assertEqual(settingsTab_widget_ui.yearly_directory_help_button.text(), "?")
self.assertEqual(settingsTab_widget_ui.settings_restore_database_button.text(),"Restore Database")
def test_spinBox(self):
'''Test the defaults'''
self.assertEqual(settingsTab_widget_ui.concurrent_reports_spin_box.value(),0)
self.assertEqual(settingsTab_widget_ui.concurrent_vendors_spin_box.value(), 0)
self.assertEqual(settingsTab_widget_ui.request_interval_spin_box.value(), 0)
self.assertEqual(settingsTab_widget_ui.request_timeout_spin_box.value(), 0)
def test_lineEdit(self):
'''Test the defaults'''
self.assertEqual(settingsTab_widget_ui.empty_cell_edit.text(),"")
self.assertEqual(settingsTab_widget_ui.other_directory_edit.text(),"")
self.assertEqual(settingsTab_widget_ui.user_agent_edit.text(),"")
self.assertEqual(settingsTab_widget_ui.yearly_directory_edit.text(),"")
if __name__ == '__main__':
unittest.main()

30
tests/test_UpdateDatabaseProgressDialog.py

@ -0,0 +1,30 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QDialog
from ui import UpdateDatabaseProgressDialog
app = QApplication(sys.argv)
update_database_progress_dialog = QDialog()
update_database_progress_dialog_ui = UpdateDatabaseProgressDialog.Ui_restore_database_dialog()
update_database_progress_dialog_ui.setupUi(update_database_progress_dialog)
class UpdateDatabaseProgressDialogTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(update_database_progress_dialog_ui.status_label.text(),"Status")
def test_buttonBox(self):
'''Test the defaults'''
okWidget = update_database_progress_dialog_ui.buttonBox.Ok
self.assertIsNotNone(okWidget)
cancelWidget = update_database_progress_dialog_ui.buttonBox.Cancel
self.assertIsNotNone(cancelWidget)
def test_progressBar(self):
'''Test the defaults'''
self.assertEqual(update_database_progress_dialog_ui.progressbar.text(),"0%")
self.assertEqual(update_database_progress_dialog_ui.progressbar.value(), 0)
if __name__ == '__main__':
unittest.main()

24
tests/test_VendorResultsWidget.py

@ -0,0 +1,24 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import VendorResultsWidget
app = QApplication(sys.argv)
vendor_results_widget = QWidget()
vendor_results_ui = VendorResultsWidget.Ui_VendorResultsWidget()
vendor_results_ui.setupUi(vendor_results_widget)
class VendorResultsWidgetTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(vendor_results_ui.status_label.text(),"Success")
self.assertEqual(vendor_results_ui.vendor_label.text(),"Bioone")
def test_button(self):
self.assertEqual(vendor_results_ui.collapse_button.text(), "Collapse")
self.assertEqual(vendor_results_ui.expand_button.text(), "Expand")
if __name__ == '__main__':
unittest.main()

65
tests/test_VisualTab.py

@ -0,0 +1,65 @@
import unittest
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from ui import VisualTab
app = QApplication(sys.argv)
visualTab_widget = QWidget()
visualTab_widget_ui = VisualTab.Ui_visual_tab()
visualTab_widget_ui.setupUi(visualTab_widget)
class VisualTabTests(unittest.TestCase):
def test_defaults(self):
'''Test the defaults'''
self.assertEqual(visualTab_widget_ui.label_46.text(), "IMPORTANT")
self.assertEqual(visualTab_widget_ui.label_47.text(), "Name must correspond to Report:")
self.assertEqual(visualTab_widget_ui.label_48.text(), "Examples : Report is PR, Name must be a Platform")
self.assertEqual(visualTab_widget_ui.label_49.text(), "Report is DR, Name must be a Database")
self.assertEqual(visualTab_widget_ui.label_50.text(), "Report is TR, Name must be a Title")
self.assertEqual(visualTab_widget_ui.label_45.text(), "Select Chart Type")
self.assertEqual(visualTab_widget_ui.label.text(), "Create Chart")
self.assertEqual(visualTab_widget_ui.label_14.text(), "Metric Type * :")
self.assertEqual(visualTab_widget_ui.label_15.text(), "Required fields*")
self.assertEqual(visualTab_widget_ui.label_8.text(), "Name * :")
self.assertEqual(visualTab_widget_ui.label_16.text(), "File Name")
self.assertEqual(visualTab_widget_ui.label_36.text(), "Chart Title")
self.assertEqual(visualTab_widget_ui.label_42.text(), "Customize Chart")
self.assertEqual(visualTab_widget_ui.label_43.text(), "Horizontal Axis Title")
self.assertEqual(visualTab_widget_ui.label_44.text(), "Vertical Axis Title")
self.assertEqual(visualTab_widget_ui.search_end_year_parameter_label_2.text(), "End year")
self.assertEqual(visualTab_widget_ui.search_report_parameter_label_2.text(), "Report")
self.assertEqual(visualTab_widget_ui.search_start_year_parameter_label_2.text(),"Start Year")
def test_combobox(self):
'''Test the defaults'''
self.assertEqual(visualTab_widget_ui.metric_Type_comboBox.isEditable(),False)
self.assertEqual(visualTab_widget_ui.metric_Type_comboBox.currentText(),"")
self.assertEqual(visualTab_widget_ui.search_report_parameter_combobox_2.isEditable(), False)
self.assertEqual(visualTab_widget_ui.search_report_parameter_combobox_2.currentText(), "")
def test_radioButrton(self):
'''Test the defaults'''
self.assertEqual(visualTab_widget_ui.radioButton.text(),"Horizontal Bar")
self.assertEqual(visualTab_widget_ui.radioButton_3.text(), "Vertical Bar")
self.assertEqual(visualTab_widget_ui.radioButton_4.text(), "Line")
def test_lineEdit(self):
'''Test the defaults'''
self.assertEqual(visualTab_widget_ui.name_lineEdit.text(),"")
self.assertEqual(visualTab_widget_ui.chart_title_lineEdit.text(), "")
self.assertEqual(visualTab_widget_ui.file_name_lineEdit.text(), "")
self.assertEqual(visualTab_widget_ui.horizontal_axis_lineEdit.text(), "")
self.assertEqual(visualTab_widget_ui.vertical_axis_lineEdit.text(), "")
def test_pushButton(self):
'''Test the defaults'''
self.assertEqual(visualTab_widget_ui.create_chart_button.text(),"Create Chart")
def test_dateEdit(self):
'''Test the defaults'''
self.assertEqual(visualTab_widget_ui.search_end_year_parameter_dateedit_2.text(),"2000")
self.assertEqual(visualTab_widget_ui.search_start_year_parameter_dateedit_2.text(),"2000")
if __name__ == '__main__':
unittest.main()

146
ui/AddVendorDialog.py

@ -0,0 +1,146 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'AddVendorDialog.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_addVendorDialog(object):
def setupUi(self, addVendorDialog):
addVendorDialog.setObjectName("addVendorDialog")
addVendorDialog.resize(600, 620)
font = QtGui.QFont()
font.setPointSize(11)
addVendorDialog.setFont(font)
self.gridLayout = QtWidgets.QGridLayout(addVendorDialog)
self.gridLayout.setObjectName("gridLayout")
self.buttonBox = QtWidgets.QDialogButtonBox(addVendorDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1)
self.frame = QtWidgets.QFrame(addVendorDialog)
self.frame.setObjectName("frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
self.gridLayout_2.setSpacing(20)
self.gridLayout_2.setObjectName("gridLayout_2")
self.label_7 = QtWidgets.QLabel(self.frame)
self.label_7.setObjectName("label_7")
self.gridLayout_2.addWidget(self.label_7, 9, 0, 1, 1, QtCore.Qt.AlignTop)
self.label_3 = QtWidgets.QLabel(self.frame)
self.label_3.setObjectName("label_3")
self.gridLayout_2.addWidget(self.label_3, 2, 0, 1, 1)
self.label_5 = QtWidgets.QLabel(self.frame)
self.label_5.setObjectName("label_5")
self.gridLayout_2.addWidget(self.label_5, 6, 0, 1, 1)
self.companiesEdit = QtWidgets.QPlainTextEdit(self.frame)
self.companiesEdit.setObjectName("companiesEdit")
self.gridLayout_2.addWidget(self.companiesEdit, 10, 1, 1, 1)
self.name_validation_label = QtWidgets.QLabel(self.frame)
self.name_validation_label.setObjectName("name_validation_label")
self.gridLayout_2.addWidget(self.name_validation_label, 1, 1, 1, 1)
self.label_6 = QtWidgets.QLabel(self.frame)
self.label_6.setObjectName("label_6")
self.gridLayout_2.addWidget(self.label_6, 7, 0, 1, 1)
self.frame_2 = QtWidgets.QFrame(self.frame)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.non_Sushi_check_box = QtWidgets.QCheckBox(self.frame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.non_Sushi_check_box.sizePolicy().hasHeightForWidth())
self.non_Sushi_check_box.setSizePolicy(sizePolicy)
self.non_Sushi_check_box.setText("")
self.non_Sushi_check_box.setObjectName("non_Sushi_check_box")
self.horizontalLayout.addWidget(self.non_Sushi_check_box)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.non_sushi_help_button = QtWidgets.QPushButton(self.frame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.non_sushi_help_button.sizePolicy().hasHeightForWidth())
self.non_sushi_help_button.setSizePolicy(sizePolicy)
self.non_sushi_help_button.setText("")
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/help_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.non_sushi_help_button.setIcon(icon)
self.non_sushi_help_button.setObjectName("non_sushi_help_button")
self.horizontalLayout.addWidget(self.non_sushi_help_button)
self.gridLayout_2.addWidget(self.frame_2, 8, 1, 1, 1)
self.label_8 = QtWidgets.QLabel(self.frame)
self.label_8.setObjectName("label_8")
self.gridLayout_2.addWidget(self.label_8, 8, 0, 1, 1)
self.label_2 = QtWidgets.QLabel(self.frame)
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 4, 0, 1, 1)
self.requestorIdEdit = QtWidgets.QLineEdit(self.frame)
self.requestorIdEdit.setObjectName("requestorIdEdit")
self.gridLayout_2.addWidget(self.requestorIdEdit, 5, 1, 1, 1)
self.customerIdEdit = QtWidgets.QLineEdit(self.frame)
self.customerIdEdit.setObjectName("customerIdEdit")
self.gridLayout_2.addWidget(self.customerIdEdit, 4, 1, 1, 1)
self.nameEdit = QtWidgets.QLineEdit(self.frame)
self.nameEdit.setObjectName("nameEdit")
self.gridLayout_2.addWidget(self.nameEdit, 0, 1, 1, 1)
self.label_9 = QtWidgets.QLabel(self.frame)
self.label_9.setObjectName("label_9")
self.gridLayout_2.addWidget(self.label_9, 10, 0, 1, 1, QtCore.Qt.AlignTop)
self.url_validation_label = QtWidgets.QLabel(self.frame)
self.url_validation_label.setObjectName("url_validation_label")
self.gridLayout_2.addWidget(self.url_validation_label, 3, 1, 1, 1)
self.baseUrlEdit = QtWidgets.QLineEdit(self.frame)
self.baseUrlEdit.setObjectName("baseUrlEdit")
self.gridLayout_2.addWidget(self.baseUrlEdit, 2, 1, 1, 1)
self.apiKeyEdit = QtWidgets.QLineEdit(self.frame)
self.apiKeyEdit.setObjectName("apiKeyEdit")
self.gridLayout_2.addWidget(self.apiKeyEdit, 6, 1, 1, 1)
self.descriptionEdit = QtWidgets.QPlainTextEdit(self.frame)
self.descriptionEdit.setObjectName("descriptionEdit")
self.gridLayout_2.addWidget(self.descriptionEdit, 9, 1, 1, 1)
self.label = QtWidgets.QLabel(self.frame)
self.label.setObjectName("label")
self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
self.platformEdit = QtWidgets.QLineEdit(self.frame)
self.platformEdit.setObjectName("platformEdit")
self.gridLayout_2.addWidget(self.platformEdit, 7, 1, 1, 1)
self.label_4 = QtWidgets.QLabel(self.frame)
self.label_4.setObjectName("label_4")
self.gridLayout_2.addWidget(self.label_4, 5, 0, 1, 1)
self.gridLayout.addWidget(self.frame, 0, 0, 1, 1)
self.retranslateUi(addVendorDialog)
QtCore.QMetaObject.connectSlotsByName(addVendorDialog)
addVendorDialog.setTabOrder(self.nameEdit, self.baseUrlEdit)
addVendorDialog.setTabOrder(self.baseUrlEdit, self.customerIdEdit)
addVendorDialog.setTabOrder(self.customerIdEdit, self.requestorIdEdit)
addVendorDialog.setTabOrder(self.requestorIdEdit, self.apiKeyEdit)
addVendorDialog.setTabOrder(self.apiKeyEdit, self.platformEdit)
addVendorDialog.setTabOrder(self.platformEdit, self.non_Sushi_check_box)
addVendorDialog.setTabOrder(self.non_Sushi_check_box, self.non_sushi_help_button)
addVendorDialog.setTabOrder(self.non_sushi_help_button, self.descriptionEdit)
addVendorDialog.setTabOrder(self.descriptionEdit, self.companiesEdit)
def retranslateUi(self, addVendorDialog):
_translate = QtCore.QCoreApplication.translate
addVendorDialog.setWindowTitle(_translate("addVendorDialog", "Add Vendor"))
self.label_7.setText(_translate("addVendorDialog", "Description"))
self.label_3.setText(_translate("addVendorDialog", "Base URL"))
self.label_5.setText(_translate("addVendorDialog", "API Key"))
self.name_validation_label.setText(_translate("addVendorDialog", "Validation label"))
self.label_6.setText(_translate("addVendorDialog", "Platform"))
self.label_8.setText(_translate("addVendorDialog", "Non-SUSHI Vendor"))
self.label_2.setText(_translate("addVendorDialog", "Customer ID"))
self.label_9.setText(_translate("addVendorDialog", "Third party provider"))
self.url_validation_label.setText(_translate("addVendorDialog", "Validation label"))
self.label.setText(_translate("addVendorDialog", "Name"))
self.label_4.setText(_translate("addVendorDialog", "Requestor ID"))
import Resources_rc

221
ui/AddVendorDialog.ui

@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>addVendorDialog</class>
<widget class="QDialog" name="addVendorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>620</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Add Vendor</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QFrame" name="frame">
<layout class="QGridLayout" name="gridLayout_2">
<property name="spacing">
<number>20</number>
</property>
<item row="9" column="0" alignment="Qt::AlignTop">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Base URL</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>API Key</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QPlainTextEdit" name="companiesEdit"/>
</item>
<item row="1" column="1">
<widget class="QLabel" name="name_validation_label">
<property name="text">
<string>Validation label</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Platform</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QFrame" name="frame_2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="non_Sushi_check_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="non_sushi_help_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Non-SUSHI Vendor</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Customer ID</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="requestorIdEdit"/>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="customerIdEdit"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="nameEdit"/>
</item>
<item row="10" column="0" alignment="Qt::AlignTop">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Third party provider</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="url_validation_label">
<property name="text">
<string>Validation label</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="baseUrlEdit"/>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="apiKeyEdit"/>
</item>
<item row="9" column="1">
<widget class="QPlainTextEdit" name="descriptionEdit"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="platformEdit"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Requestor ID</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>nameEdit</tabstop>
<tabstop>baseUrlEdit</tabstop>
<tabstop>customerIdEdit</tabstop>
<tabstop>requestorIdEdit</tabstop>
<tabstop>apiKeyEdit</tabstop>
<tabstop>platformEdit</tabstop>
<tabstop>non_Sushi_check_box</tabstop>
<tabstop>non_sushi_help_button</tabstop>
<tabstop>descriptionEdit</tabstop>
<tabstop>companiesEdit</tabstop>
</tabstops>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

158
ui/CostsTab.py

@ -0,0 +1,158 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'CostsTab.ui'
#
# Created by: PyQt5 UI code generator 5.14.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_costs_tab(object):
def setupUi(self, costs_tab):
costs_tab.setObjectName("costs_tab")
costs_tab.resize(898, 671)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/tab_icons/costs_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
costs_tab.setWindowIcon(icon)
self.horizontalLayout = QtWidgets.QHBoxLayout(costs_tab)
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(120, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.frame = QtWidgets.QFrame(costs_tab)
self.frame.setObjectName("frame")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame)
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.costs_parameters_frame = QtWidgets.QFrame(self.frame)
self.costs_parameters_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.costs_parameters_frame.setObjectName("costs_parameters_frame")
self.formLayout_3 = QtWidgets.QFormLayout(self.costs_parameters_frame)
self.formLayout_3.setObjectName("formLayout_3")
self.costs_report_parameter_label = QtWidgets.QLabel(self.costs_parameters_frame)
self.costs_report_parameter_label.setObjectName("costs_report_parameter_label")
self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.costs_report_parameter_label)
self.costs_report_parameter_combobox = QtWidgets.QComboBox(self.costs_parameters_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.costs_report_parameter_combobox.sizePolicy().hasHeightForWidth())
self.costs_report_parameter_combobox.setSizePolicy(sizePolicy)
self.costs_report_parameter_combobox.setMinimumSize(QtCore.QSize(300, 0))
self.costs_report_parameter_combobox.setObjectName("costs_report_parameter_combobox")
self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.costs_report_parameter_combobox)
self.costs_vendor_parameter_label = QtWidgets.QLabel(self.costs_parameters_frame)
self.costs_vendor_parameter_label.setObjectName("costs_vendor_parameter_label")
self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.costs_vendor_parameter_label)
self.costs_vendor_parameter_combobox = QtWidgets.QComboBox(self.costs_parameters_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.costs_vendor_parameter_combobox.sizePolicy().hasHeightForWidth())
self.costs_vendor_parameter_combobox.setSizePolicy(sizePolicy)
self.costs_vendor_parameter_combobox.setMinimumSize(QtCore.QSize(300, 0))
self.costs_vendor_parameter_combobox.setEditable(False)
self.costs_vendor_parameter_combobox.setObjectName("costs_vendor_parameter_combobox")
self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.costs_vendor_parameter_combobox)
self.costs_year_parameter_label = QtWidgets.QLabel(self.costs_parameters_frame)
self.costs_year_parameter_label.setObjectName("costs_year_parameter_label")
self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.costs_year_parameter_label)
self.costs_year_parameter_dateedit = QtWidgets.QDateEdit(self.costs_parameters_frame)
self.costs_year_parameter_dateedit.setObjectName("costs_year_parameter_dateedit")
self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.costs_year_parameter_dateedit)
self.costs_name_parameter_label = QtWidgets.QLabel(self.costs_parameters_frame)
self.costs_name_parameter_label.setObjectName("costs_name_parameter_label")
self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.costs_name_parameter_label)
self.costs_name_parameter_combobox = QtWidgets.QComboBox(self.costs_parameters_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.costs_name_parameter_combobox.sizePolicy().hasHeightForWidth())
self.costs_name_parameter_combobox.setSizePolicy(sizePolicy)
self.costs_name_parameter_combobox.setMinimumSize(QtCore.QSize(300, 0))
self.costs_name_parameter_combobox.setEditable(True)
self.costs_name_parameter_combobox.setObjectName("costs_name_parameter_combobox")
self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.costs_name_parameter_combobox)
self.verticalLayout_2.addWidget(self.costs_parameters_frame)
self.costs_values_frame = QtWidgets.QFrame(self.frame)
self.costs_values_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.costs_values_frame.setObjectName("costs_values_frame")
self.formLayout = QtWidgets.QFormLayout(self.costs_values_frame)
self.formLayout.setObjectName("formLayout")
self.costs_cost_in_original_currency_label = QtWidgets.QLabel(self.costs_values_frame)
self.costs_cost_in_original_currency_label.setObjectName("costs_cost_in_original_currency_label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.costs_cost_in_original_currency_label)
self.costs_cost_in_original_currency_doublespinbox = QtWidgets.QDoubleSpinBox(self.costs_values_frame)
self.costs_cost_in_original_currency_doublespinbox.setEnabled(False)
self.costs_cost_in_original_currency_doublespinbox.setMaximum(999999999.99)
self.costs_cost_in_original_currency_doublespinbox.setObjectName("costs_cost_in_original_currency_doublespinbox")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.costs_cost_in_original_currency_doublespinbox)
self.costs_original_currency_label = QtWidgets.QLabel(self.costs_values_frame)
self.costs_original_currency_label.setObjectName("costs_original_currency_label")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.costs_original_currency_label)
self.costs_original_currency_value_combobox = QtWidgets.QComboBox(self.costs_values_frame)
self.costs_original_currency_value_combobox.setEnabled(False)
self.costs_original_currency_value_combobox.setEditable(True)
self.costs_original_currency_value_combobox.setObjectName("costs_original_currency_value_combobox")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.costs_original_currency_value_combobox)
self.costs_cost_in_local_currency_label = QtWidgets.QLabel(self.costs_values_frame)
self.costs_cost_in_local_currency_label.setObjectName("costs_cost_in_local_currency_label")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.costs_cost_in_local_currency_label)
self.costs_cost_in_local_currency_doublespinbox = QtWidgets.QDoubleSpinBox(self.costs_values_frame)
self.costs_cost_in_local_currency_doublespinbox.setEnabled(False)
self.costs_cost_in_local_currency_doublespinbox.setMaximum(999999999.99)
self.costs_cost_in_local_currency_doublespinbox.setObjectName("costs_cost_in_local_currency_doublespinbox")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.costs_cost_in_local_currency_doublespinbox)
self.costs_cost_in_local_currency_with_tax_label = QtWidgets.QLabel(self.costs_values_frame)
self.costs_cost_in_local_currency_with_tax_label.setObjectName("costs_cost_in_local_currency_with_tax_label")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.costs_cost_in_local_currency_with_tax_label)
self.costs_cost_in_local_currency_with_tax_doublespinbox = QtWidgets.QDoubleSpinBox(self.costs_values_frame)
self.costs_cost_in_local_currency_with_tax_doublespinbox.setEnabled(False)
self.costs_cost_in_local_currency_with_tax_doublespinbox.setMaximum(999999999.99)
self.costs_cost_in_local_currency_with_tax_doublespinbox.setObjectName("costs_cost_in_local_currency_with_tax_doublespinbox")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.costs_cost_in_local_currency_with_tax_doublespinbox)
self.verticalLayout_2.addWidget(self.costs_values_frame)
self.costs_control_frame = QtWidgets.QFrame(self.frame)
self.costs_control_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.costs_control_frame.setObjectName("costs_control_frame")
self.gridLayout = QtWidgets.QGridLayout(self.costs_control_frame)
self.gridLayout.setObjectName("gridLayout")
self.costs_save_button = QtWidgets.QPushButton(self.costs_control_frame)
self.costs_save_button.setObjectName("costs_save_button")
self.gridLayout.addWidget(self.costs_save_button, 0, 0, 1, 1)
self.costs_clear_button = QtWidgets.QPushButton(self.costs_control_frame)
self.costs_clear_button.setObjectName("costs_clear_button")
self.gridLayout.addWidget(self.costs_clear_button, 0, 2, 1, 1)
self.costs_load_button = QtWidgets.QPushButton(self.costs_control_frame)
self.costs_load_button.setObjectName("costs_load_button")
self.gridLayout.addWidget(self.costs_load_button, 0, 4, 1, 1)
self.costs_import_costs_button = QtWidgets.QPushButton(self.costs_control_frame)
self.costs_import_costs_button.setObjectName("costs_import_costs_button")
self.gridLayout.addWidget(self.costs_import_costs_button, 0, 5, 1, 1)
self.verticalLayout_2.addWidget(self.costs_control_frame)
self.horizontalLayout.addWidget(self.frame)
spacerItem1 = QtWidgets.QSpacerItem(120, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.retranslateUi(costs_tab)
QtCore.QMetaObject.connectSlotsByName(costs_tab)
def retranslateUi(self, costs_tab):
_translate = QtCore.QCoreApplication.translate
costs_tab.setWindowTitle(_translate("costs_tab", "Costs"))
self.costs_report_parameter_label.setText(_translate("costs_tab", "Report"))
self.costs_vendor_parameter_label.setText(_translate("costs_tab", "Vendor"))
self.costs_year_parameter_label.setText(_translate("costs_tab", "Year"))
self.costs_year_parameter_dateedit.setDisplayFormat(_translate("costs_tab", "yyyy"))
self.costs_name_parameter_label.setText(_translate("costs_tab", "Name"))
self.costs_cost_in_original_currency_label.setText(_translate("costs_tab", "Cost in Original Currency"))
self.costs_original_currency_label.setText(_translate("costs_tab", "Original Currency"))
self.costs_cost_in_local_currency_label.setText(_translate("costs_tab", "Cost in Local Currency"))
self.costs_cost_in_local_currency_with_tax_label.setText(_translate("costs_tab", "Cost in Local Currency with Tax"))
self.costs_save_button.setText(_translate("costs_tab", "Save Costs"))
self.costs_clear_button.setText(_translate("costs_tab", "Clear"))
self.costs_load_button.setText(_translate("costs_tab", "Refresh Costs"))
self.costs_import_costs_button.setText(_translate("costs_tab", "Import Costs File"))
import Resources_rc

289
ui/CostsTab.ui

@ -0,0 +1,289 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>costs_tab</class>
<widget class="QWidget" name="costs_tab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>898</width>
<height>671</height>
</rect>
</property>
<property name="windowTitle">
<string>Costs</string>
</property>
<property name="windowIcon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/tab_icons/costs_icon.png</normaloff>:/ui/resources/tab_icons/costs_icon.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>120</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frame">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="costs_parameters_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="costs_report_parameter_label">
<property name="text">
<string>Report</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="costs_report_parameter_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="costs_vendor_parameter_label">
<property name="text">
<string>Vendor</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="costs_vendor_parameter_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="costs_year_parameter_label">
<property name="text">
<string>Year</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDateEdit" name="costs_year_parameter_dateedit">
<property name="displayFormat">
<string>yyyy</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="costs_name_parameter_label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="costs_name_parameter_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="costs_values_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="costs_cost_in_original_currency_label">
<property name="text">
<string>Cost in Original Currency</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="costs_cost_in_original_currency_doublespinbox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<double>999999999.990000009536743</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="costs_original_currency_label">
<property name="text">
<string>Original Currency</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="costs_original_currency_value_combobox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="costs_cost_in_local_currency_label">
<property name="text">
<string>Cost in Local Currency</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="costs_cost_in_local_currency_doublespinbox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<double>999999999.990000009536743</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="costs_cost_in_local_currency_with_tax_label">
<property name="text">
<string>Cost in Local Currency with Tax</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="costs_cost_in_local_currency_with_tax_doublespinbox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<double>999999999.990000009536743</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="costs_control_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="costs_save_button">
<property name="text">
<string>Save Costs</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="costs_clear_button">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="costs_load_button">
<property name="text">
<string>Refresh Costs</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QPushButton" name="costs_import_costs_button">
<property name="text">
<string>Import Costs File</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>120</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

39
ui/DisclaimerDialog.py

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'DisclaimerDialog.ui'
#
# Created by: PyQt5 UI code generator 5.14.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_dialog(object):
def setupUi(self, dialog):
dialog.setObjectName("dialog")
dialog.resize(403, 80)
self.buttonBox = QtWidgets.QDialogButtonBox(dialog)
self.buttonBox.setGeometry(QtCore.QRect(40, 50, 341, 32))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.frame = QtWidgets.QFrame(dialog)
self.frame.setGeometry(QtCore.QRect(10, 10, 381, 41))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.label = QtWidgets.QLabel(self.frame)
self.label.setGeometry(QtCore.QRect(10, 0, 371, 41))
self.label.setObjectName("label")
self.retranslateUi(dialog)
self.buttonBox.accepted.connect(dialog.accept)
self.buttonBox.rejected.connect(dialog.reject)
QtCore.QMetaObject.connectSlotsByName(dialog)
def retranslateUi(self, dialog):
_translate = QtCore.QCoreApplication.translate
dialog.setWindowTitle(_translate("dialog", "Disclaimer"))
self.label.setText(_translate("dialog", "Only reports supported by selected vendor will be retrieved!"))

97
ui/DisclaimerDialog.ui

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>dialog</class>
<widget class="QDialog" name="dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<height>80</height>
</rect>
</property>
<property name="windowTitle">
<string>Disclaimer</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>40</x>
<y>50</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QFrame" name="frame">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>381</width>
<height>41</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>0</y>
<width>371</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>Only reports supported by selected vendor will be retrieved!</string>
</property>
</widget>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

80
ui/FetchProgressDialog.py

@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'FetchProgressDialog.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_FetchProgressDialog(object):
def setupUi(self, FetchProgressDialog):
FetchProgressDialog.setObjectName("FetchProgressDialog")
FetchProgressDialog.resize(800, 600)
FetchProgressDialog.setMinimumSize(QtCore.QSize(680, 0))
font = QtGui.QFont()
font.setPointSize(9)
FetchProgressDialog.setFont(font)
self.verticalLayout = QtWidgets.QVBoxLayout(FetchProgressDialog)
self.verticalLayout.setObjectName("verticalLayout")
self.fetching_frame = QtWidgets.QFrame(FetchProgressDialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.fetching_frame.sizePolicy().hasHeightForWidth())
self.fetching_frame.setSizePolicy(sizePolicy)
self.fetching_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.fetching_frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.fetching_frame.setObjectName("fetching_frame")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.fetching_frame)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.status_label = QtWidgets.QLabel(self.fetching_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.status_label.sizePolicy().hasHeightForWidth())
self.status_label.setSizePolicy(sizePolicy)
self.status_label.setAlignment(QtCore.Qt.AlignCenter)
self.status_label.setObjectName("status_label")
self.verticalLayout_2.addWidget(self.status_label)
self.progress_bar = QtWidgets.QProgressBar(self.fetching_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.progress_bar.sizePolicy().hasHeightForWidth())
self.progress_bar.setSizePolicy(sizePolicy)
self.progress_bar.setProperty("value", 24)
self.progress_bar.setObjectName("progress_bar")
self.verticalLayout_2.addWidget(self.progress_bar)
self.verticalLayout.addWidget(self.fetching_frame)
self.results_scroll_area = QtWidgets.QScrollArea(FetchProgressDialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.results_scroll_area.sizePolicy().hasHeightForWidth())
self.results_scroll_area.setSizePolicy(sizePolicy)
self.results_scroll_area.setWidgetResizable(True)
self.results_scroll_area.setObjectName("results_scroll_area")
self.scroll_area_widget_contents = QtWidgets.QWidget()
self.scroll_area_widget_contents.setGeometry(QtCore.QRect(0, 0, 780, 480))
self.scroll_area_widget_contents.setObjectName("scroll_area_widget_contents")
self.scroll_area_vertical_layout = QtWidgets.QVBoxLayout(self.scroll_area_widget_contents)
self.scroll_area_vertical_layout.setObjectName("scroll_area_vertical_layout")
self.results_scroll_area.setWidget(self.scroll_area_widget_contents)
self.verticalLayout.addWidget(self.results_scroll_area)
self.buttonBox = QtWidgets.QDialogButtonBox(FetchProgressDialog)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Retry)
self.buttonBox.setCenterButtons(True)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(FetchProgressDialog)
QtCore.QMetaObject.connectSlotsByName(FetchProgressDialog)
def retranslateUi(self, FetchProgressDialog):
_translate = QtCore.QCoreApplication.translate
FetchProgressDialog.setWindowTitle(_translate("FetchProgressDialog", "Fetch Progress"))
self.status_label.setText(_translate("FetchProgressDialog", "Fetching..."))

113
ui/FetchProgressDialog.ui

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FetchProgressDialog</class>
<widget class="QDialog" name="FetchProgressDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>680</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Fetch Progress</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="fetching_frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="status_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fetching...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progress_bar">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>24</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QScrollArea" name="results_scroll_area">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scroll_area_widget_contents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>780</width>
<height>480</height>
</rect>
</property>
<layout class="QVBoxLayout" name="scroll_area_vertical_layout"/>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Retry</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

113
ui/FetchProgressDialog_bak.ui

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FetchProgressDialog</class>
<widget class="QDialog" name="FetchProgressDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>680</width>
<height>353</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>680</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Fetch Progress</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="fetching_frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="status_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fetching...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progress_bar">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>24</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QScrollArea" name="results_scroll_area">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scroll_area_widget_contents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>660</width>
<height>236</height>
</rect>
</property>
<layout class="QVBoxLayout" name="scroll_area_vertical_layout"/>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Retry</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

422
ui/FetchReportsTab.py

@ -0,0 +1,422 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'FetchReportsTab.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_fetch_reports_tab(object):
def setupUi(self, fetch_reports_tab):
fetch_reports_tab.setObjectName("fetch_reports_tab")
fetch_reports_tab.resize(1014, 746)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(fetch_reports_tab.sizePolicy().hasHeightForWidth())
fetch_reports_tab.setSizePolicy(sizePolicy)
fetch_reports_tab.setMinimumSize(QtCore.QSize(800, 0))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/tab_icons/fetch_reports_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
fetch_reports_tab.setWindowIcon(icon)
self.verticalLayout = QtWidgets.QVBoxLayout(fetch_reports_tab)
self.verticalLayout.setObjectName("verticalLayout")
self.frame_4 = QtWidgets.QFrame(fetch_reports_tab)
self.frame_4.setMouseTracking(True)
self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_4.setObjectName("frame_4")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.frame_4)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.label_35 = QtWidgets.QLabel(self.frame_4)
self.label_35.setMinimumSize(QtCore.QSize(15, 15))
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.label_35.setFont(font)
self.label_35.setAlignment(QtCore.Qt.AlignCenter)
self.label_35.setObjectName("label_35")
self.verticalLayout_3.addWidget(self.label_35)
self.frame_9 = QtWidgets.QFrame(self.frame_4)
self.frame_9.setMinimumSize(QtCore.QSize(0, 60))
self.frame_9.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_9.setObjectName("frame_9")
self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.frame_9)
self.horizontalLayout_10.setObjectName("horizontalLayout_10")
self.frame_28 = QtWidgets.QFrame(self.frame_9)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_28.sizePolicy().hasHeightForWidth())
self.frame_28.setSizePolicy(sizePolicy)
self.frame_28.setObjectName("frame_28")
self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.frame_28)
self.horizontalLayout_12.setSpacing(10)
self.horizontalLayout_12.setObjectName("horizontalLayout_12")
self.label_34 = QtWidgets.QLabel(self.frame_28)
self.label_34.setObjectName("label_34")
self.horizontalLayout_12.addWidget(self.label_34)
self.All_reports_edit_fetch = QtWidgets.QDateEdit(self.frame_28)
self.All_reports_edit_fetch.setDateTime(QtCore.QDateTime(QtCore.QDate(2020, 1, 1), QtCore.QTime(0, 0, 0)))
self.All_reports_edit_fetch.setObjectName("All_reports_edit_fetch")
self.horizontalLayout_12.addWidget(self.All_reports_edit_fetch)
self.horizontalLayout_10.addWidget(self.frame_28)
self.fetch_all_data_button = QtWidgets.QPushButton(self.frame_9)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.fetch_all_data_button.sizePolicy().hasHeightForWidth())
self.fetch_all_data_button.setSizePolicy(sizePolicy)
self.fetch_all_data_button.setMaximumSize(QtCore.QSize(300, 16777215))
self.fetch_all_data_button.setObjectName("fetch_all_data_button")
self.horizontalLayout_10.addWidget(self.fetch_all_data_button)
self.verticalLayout_3.addWidget(self.frame_9)
spacerItem = QtWidgets.QSpacerItem(20, 45, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
self.verticalLayout_3.addItem(spacerItem)
self.Adv_Fetch_text = QtWidgets.QLabel(self.frame_4)
self.Adv_Fetch_text.setMaximumSize(QtCore.QSize(16777215, 20))
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(16)
font.setBold(True)
font.setItalic(False)
font.setUnderline(False)
font.setWeight(75)
self.Adv_Fetch_text.setFont(font)
self.Adv_Fetch_text.setAlignment(QtCore.Qt.AlignCenter)
self.Adv_Fetch_text.setObjectName("Adv_Fetch_text")
self.verticalLayout_3.addWidget(self.Adv_Fetch_text)
self.frame_5 = QtWidgets.QFrame(self.frame_4)
self.frame_5.setObjectName("frame_5")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.frame_5)
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.frame_10 = QtWidgets.QFrame(self.frame_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_10.sizePolicy().hasHeightForWidth())
self.frame_10.setSizePolicy(sizePolicy)
self.frame_10.setMinimumSize(QtCore.QSize(200, 0))
self.frame_10.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_10.setObjectName("frame_10")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.frame_10)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.label_11 = QtWidgets.QLabel(self.frame_10)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_11.setFont(font)
self.label_11.setObjectName("label_11")
self.verticalLayout_4.addWidget(self.label_11)
self.horizontalFrame = QtWidgets.QFrame(self.frame_10)
self.horizontalFrame.setObjectName("horizontalFrame")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.horizontalFrame)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.select_vendors_button_fetch = QtWidgets.QPushButton(self.horizontalFrame)
self.select_vendors_button_fetch.setObjectName("select_vendors_button_fetch")
self.horizontalLayout_4.addWidget(self.select_vendors_button_fetch)
self.deselect_vendors_button_fetch = QtWidgets.QPushButton(self.horizontalFrame)
self.deselect_vendors_button_fetch.setObjectName("deselect_vendors_button_fetch")
self.horizontalLayout_4.addWidget(self.deselect_vendors_button_fetch)
self.verticalLayout_4.addWidget(self.horizontalFrame)
self.vendors_list_view_fetch = QtWidgets.QListView(self.frame_10)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
self.vendors_list_view_fetch.setFont(font)
self.vendors_list_view_fetch.setAlternatingRowColors(True)
self.vendors_list_view_fetch.setObjectName("vendors_list_view_fetch")
self.verticalLayout_4.addWidget(self.vendors_list_view_fetch)
self.horizontalLayout_3.addWidget(self.frame_10)
self.frame_11 = QtWidgets.QFrame(self.frame_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_11.sizePolicy().hasHeightForWidth())
self.frame_11.setSizePolicy(sizePolicy)
self.frame_11.setMinimumSize(QtCore.QSize(200, 0))
self.frame_11.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_11.setObjectName("frame_11")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.frame_11)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.label_12 = QtWidgets.QLabel(self.frame_11)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_12.setFont(font)
self.label_12.setObjectName("label_12")
self.verticalLayout_5.addWidget(self.label_12)
self.horizontalFrame_2 = QtWidgets.QFrame(self.frame_11)
self.horizontalFrame_2.setObjectName("horizontalFrame_2")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.horizontalFrame_2)
self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.select_report_types_button_fetch = QtWidgets.QPushButton(self.horizontalFrame_2)
self.select_report_types_button_fetch.setObjectName("select_report_types_button_fetch")
self.horizontalLayout_6.addWidget(self.select_report_types_button_fetch)
self.deselect_report_types_button_fetch = QtWidgets.QPushButton(self.horizontalFrame_2)
self.deselect_report_types_button_fetch.setObjectName("deselect_report_types_button_fetch")
self.horizontalLayout_6.addWidget(self.deselect_report_types_button_fetch)
self.report_types_help_button = QtWidgets.QPushButton(self.horizontalFrame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.report_types_help_button.sizePolicy().hasHeightForWidth())
self.report_types_help_button.setSizePolicy(sizePolicy)
self.report_types_help_button.setText("")
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/ui/resources/help_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.report_types_help_button.setIcon(icon1)
self.report_types_help_button.setObjectName("report_types_help_button")
self.horizontalLayout_6.addWidget(self.report_types_help_button)
self.verticalLayout_5.addWidget(self.horizontalFrame_2)
self.report_types_list_view = QtWidgets.QListView(self.frame_11)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
self.report_types_list_view.setFont(font)
self.report_types_list_view.setAlternatingRowColors(True)
self.report_types_list_view.setObjectName("report_types_list_view")
self.verticalLayout_5.addWidget(self.report_types_list_view)
self.horizontalLayout_3.addWidget(self.frame_11)
self.frame_7 = QtWidgets.QFrame(self.frame_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_7.sizePolicy().hasHeightForWidth())
self.frame_7.setSizePolicy(sizePolicy)
self.frame_7.setMinimumSize(QtCore.QSize(200, 0))
self.frame_7.setObjectName("frame_7")
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.frame_7)
self.verticalLayout_7.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_7.setObjectName("verticalLayout_7")
self.frame_14 = QtWidgets.QFrame(self.frame_7)
self.frame_14.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_14.setObjectName("frame_14")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame_14)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.label_8 = QtWidgets.QLabel(self.frame_14)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_8.sizePolicy().hasHeightForWidth())
self.label_8.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_8.setFont(font)
self.label_8.setObjectName("label_8")
self.verticalLayout_2.addWidget(self.label_8)
self.frame_6 = QtWidgets.QFrame(self.frame_14)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_6.sizePolicy().hasHeightForWidth())
self.frame_6.setSizePolicy(sizePolicy)
self.frame_6.setMinimumSize(QtCore.QSize(0, 0))
self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_6.setObjectName("frame_6")
self.gridLayout = QtWidgets.QGridLayout(self.frame_6)
self.gridLayout.setSpacing(20)
self.gridLayout.setObjectName("gridLayout")
self.end_date_edit_fetch_year = QtWidgets.QDateEdit(self.frame_6)
self.end_date_edit_fetch_year.setDateTime(QtCore.QDateTime(QtCore.QDate(2020, 1, 1), QtCore.QTime(0, 0, 0)))
self.end_date_edit_fetch_year.setObjectName("end_date_edit_fetch_year")
self.gridLayout.addWidget(self.end_date_edit_fetch_year, 3, 1, 1, 1)
self.begin_month_combo_box = QtWidgets.QComboBox(self.frame_6)
self.begin_month_combo_box.setObjectName("begin_month_combo_box")
self.gridLayout.addWidget(self.begin_month_combo_box, 0, 2, 1, 1)
self.label_9 = QtWidgets.QLabel(self.frame_6)
self.label_9.setObjectName("label_9")
self.gridLayout.addWidget(self.label_9, 0, 0, 1, 1)
self.end_month_combo_box = QtWidgets.QComboBox(self.frame_6)
self.end_month_combo_box.setObjectName("end_month_combo_box")
self.gridLayout.addWidget(self.end_month_combo_box, 3, 2, 1, 1)
self.begin_date_edit_fetch_year = QtWidgets.QDateEdit(self.frame_6)
self.begin_date_edit_fetch_year.setDate(QtCore.QDate(2020, 1, 1))
self.begin_date_edit_fetch_year.setObjectName("begin_date_edit_fetch_year")
self.gridLayout.addWidget(self.begin_date_edit_fetch_year, 0, 1, 1, 1)
self.label_10 = QtWidgets.QLabel(self.frame_6)
self.label_10.setObjectName("label_10")
self.gridLayout.addWidget(self.label_10, 3, 0, 1, 1)
self.verticalLayout_2.addWidget(self.frame_6)
self.custom_dir_frame = QtWidgets.QFrame(self.frame_14)
self.custom_dir_frame.setMinimumSize(QtCore.QSize(0, 0))
self.custom_dir_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.custom_dir_frame.setObjectName("custom_dir_frame")
self.verticalLayout_26 = QtWidgets.QVBoxLayout(self.custom_dir_frame)
self.verticalLayout_26.setObjectName("verticalLayout_26")
self.frame = QtWidgets.QFrame(self.custom_dir_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
self.frame.setSizePolicy(sizePolicy)
self.frame.setMaximumSize(QtCore.QSize(16777215, 16777215))
self.frame.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame.setFrameShadow(QtWidgets.QFrame.Plain)
self.frame.setObjectName("frame")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_38 = QtWidgets.QLabel(self.frame)
self.label_38.setAlignment(QtCore.Qt.AlignCenter)
self.label_38.setObjectName("label_38")
self.horizontalLayout.addWidget(self.label_38)
self.date_range_help_button = QtWidgets.QPushButton(self.frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.date_range_help_button.sizePolicy().hasHeightForWidth())
self.date_range_help_button.setSizePolicy(sizePolicy)
self.date_range_help_button.setMaximumSize(QtCore.QSize(16777215, 16777215))
self.date_range_help_button.setText("")
self.date_range_help_button.setIcon(icon1)
self.date_range_help_button.setObjectName("date_range_help_button")
self.horizontalLayout.addWidget(self.date_range_help_button)
self.verticalLayout_26.addWidget(self.frame)
self.frame_2 = QtWidgets.QFrame(self.custom_dir_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth())
self.frame_2.setSizePolicy(sizePolicy)
self.frame_2.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Plain)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setSpacing(0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label = QtWidgets.QLabel(self.frame_2)
self.label.setObjectName("label")
self.horizontalLayout_2.addWidget(self.label)
self.date_range_help_button2 = QtWidgets.QPushButton(self.frame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.date_range_help_button2.sizePolicy().hasHeightForWidth())
self.date_range_help_button2.setSizePolicy(sizePolicy)
self.date_range_help_button2.setText("")
self.date_range_help_button2.setIcon(icon1)
self.date_range_help_button2.setObjectName("date_range_help_button2")
self.horizontalLayout_2.addWidget(self.date_range_help_button2)
self.verticalLayout_26.addWidget(self.frame_2)
self.frame_3 = QtWidgets.QFrame(self.custom_dir_frame)
self.frame_3.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Plain)
self.frame_3.setObjectName("frame_3")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.frame_3)
self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_5.setSpacing(0)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.label_41 = QtWidgets.QLabel(self.frame_3)
self.label_41.setAlignment(QtCore.Qt.AlignCenter)
self.label_41.setObjectName("label_41")
self.horizontalLayout_5.addWidget(self.label_41)
self.date_range_help_button3 = QtWidgets.QPushButton(self.frame_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.date_range_help_button3.sizePolicy().hasHeightForWidth())
self.date_range_help_button3.setSizePolicy(sizePolicy)
self.date_range_help_button3.setText("")
self.date_range_help_button3.setIcon(icon1)
self.date_range_help_button3.setObjectName("date_range_help_button3")
self.horizontalLayout_5.addWidget(self.date_range_help_button3)
self.verticalLayout_26.addWidget(self.frame_3)
self.frame_39 = QtWidgets.QFrame(self.custom_dir_frame)
self.frame_39.setObjectName("frame_39")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.frame_39)
self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.custom_dir_edit = QtWidgets.QLineEdit(self.frame_39)
self.custom_dir_edit.setObjectName("custom_dir_edit")
self.horizontalLayout_7.addWidget(self.custom_dir_edit)
self.custom_dir_button = QtWidgets.QPushButton(self.frame_39)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.custom_dir_button.sizePolicy().hasHeightForWidth())
self.custom_dir_button.setSizePolicy(sizePolicy)
self.custom_dir_button.setObjectName("custom_dir_button")
self.horizontalLayout_7.addWidget(self.custom_dir_button)
self.verticalLayout_26.addWidget(self.frame_39)
self.verticalLayout_2.addWidget(self.custom_dir_frame)
self.verticalLayout_7.addWidget(self.frame_14)
self.frame_13 = QtWidgets.QFrame(self.frame_7)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_13.sizePolicy().hasHeightForWidth())
self.frame_13.setSizePolicy(sizePolicy)
self.frame_13.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_13.setObjectName("frame_13")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_13)
self.gridLayout_2.setObjectName("gridLayout_2")
self.fetch_advanced_button = QtWidgets.QPushButton(self.frame_13)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.fetch_advanced_button.sizePolicy().hasHeightForWidth())
self.fetch_advanced_button.setSizePolicy(sizePolicy)
self.fetch_advanced_button.setObjectName("fetch_advanced_button")
self.gridLayout_2.addWidget(self.fetch_advanced_button, 1, 1, 1, 1)
self.verticalLayout_7.addWidget(self.frame_13)
self.horizontalLayout_3.addWidget(self.frame_7)
self.verticalLayout_3.addWidget(self.frame_5)
self.verticalLayout.addWidget(self.frame_4)
self.label_2 = QtWidgets.QLabel(fetch_reports_tab)
self.label_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_2.setObjectName("label_2")
self.verticalLayout.addWidget(self.label_2)
self.retranslateUi(fetch_reports_tab)
QtCore.QMetaObject.connectSlotsByName(fetch_reports_tab)
fetch_reports_tab.setTabOrder(self.All_reports_edit_fetch, self.fetch_all_data_button)
fetch_reports_tab.setTabOrder(self.fetch_all_data_button, self.select_vendors_button_fetch)
fetch_reports_tab.setTabOrder(self.select_vendors_button_fetch, self.deselect_vendors_button_fetch)
fetch_reports_tab.setTabOrder(self.deselect_vendors_button_fetch, self.vendors_list_view_fetch)
fetch_reports_tab.setTabOrder(self.vendors_list_view_fetch, self.select_report_types_button_fetch)
fetch_reports_tab.setTabOrder(self.select_report_types_button_fetch, self.deselect_report_types_button_fetch)
fetch_reports_tab.setTabOrder(self.deselect_report_types_button_fetch, self.report_types_help_button)
fetch_reports_tab.setTabOrder(self.report_types_help_button, self.report_types_list_view)
fetch_reports_tab.setTabOrder(self.report_types_list_view, self.end_date_edit_fetch_year)
fetch_reports_tab.setTabOrder(self.end_date_edit_fetch_year, self.custom_dir_edit)
fetch_reports_tab.setTabOrder(self.custom_dir_edit, self.custom_dir_button)
fetch_reports_tab.setTabOrder(self.custom_dir_button, self.fetch_advanced_button)
def retranslateUi(self, fetch_reports_tab):
_translate = QtCore.QCoreApplication.translate
fetch_reports_tab.setWindowTitle(_translate("fetch_reports_tab", "Fetch Report"))
self.label_35.setText(_translate("fetch_reports_tab", "Fetch All Reports"))
self.label_34.setText(_translate("fetch_reports_tab", "Year"))
self.All_reports_edit_fetch.setDisplayFormat(_translate("fetch_reports_tab", "yyyy"))
self.fetch_all_data_button.setText(_translate("fetch_reports_tab", "Fetch All Reports"))
self.Adv_Fetch_text.setText(_translate("fetch_reports_tab", "Advanced Fetch Reports"))
self.label_11.setText(_translate("fetch_reports_tab", "Select Vendors"))
self.select_vendors_button_fetch.setText(_translate("fetch_reports_tab", "Select All"))
self.deselect_vendors_button_fetch.setText(_translate("fetch_reports_tab", "Deselect All"))
self.label_12.setText(_translate("fetch_reports_tab", "Select Report Types"))
self.select_report_types_button_fetch.setText(_translate("fetch_reports_tab", "Select All"))
self.deselect_report_types_button_fetch.setText(_translate("fetch_reports_tab", "Deselect All"))
self.label_8.setText(_translate("fetch_reports_tab", "Date Range"))
self.end_date_edit_fetch_year.setDisplayFormat(_translate("fetch_reports_tab", "yyyy"))
self.label_9.setText(_translate("fetch_reports_tab", "Begin Date"))
self.begin_date_edit_fetch_year.setDisplayFormat(_translate("fetch_reports_tab", "yyyy"))
self.label_10.setText(_translate("fetch_reports_tab", "End Date"))
self.label_38.setText(_translate("fetch_reports_tab", "Date range is not a calendar year"))
self.label.setText(_translate("fetch_reports_tab", "The date range contains months with no available data"))
self.label_41.setText(_translate("fetch_reports_tab", "Report(s) will be saved to:"))
self.custom_dir_button.setText(_translate("fetch_reports_tab", "Change"))
self.fetch_advanced_button.setText(_translate("fetch_reports_tab", "Fetch Selected Reports"))
self.label_2.setText(_translate("fetch_reports_tab", "Note: Yearly reports cover all available data for one calender year. Only yearly reports are added to the search database."))
import Resources_rc

801
ui/FetchReportsTab.ui

@ -0,0 +1,801 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>fetch_reports_tab</class>
<widget class="QWidget" name="fetch_reports_tab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1014</width>
<height>746</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Fetch Report</string>
</property>
<property name="windowIcon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/tab_icons/fetch_reports_icon.png</normaloff>:/ui/resources/tab_icons/fetch_reports_icon.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame_4">
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_35">
<property name="minimumSize">
<size>
<width>15</width>
<height>15</height>
</size>
</property>
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Fetch All Reports</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_9">
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QFrame" name="frame_28">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="spacing">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label_34">
<property name="text">
<string>Year</string>
</property>
</widget>
</item>
<item>
<widget class="QDateEdit" name="All_reports_edit_fetch">
<property name="dateTime">
<datetime>
<hour>0</hour>
<minute>0</minute>
<second>0</second>
<year>2020</year>
<month>1</month>
<day>1</day>
</datetime>
</property>
<property name="displayFormat">
<string>yyyy</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="fetch_all_data_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Fetch All Reports</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>45</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="Adv_Fetch_text">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>16</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>Advanced Fetch Reports</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_5">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label_11">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Select Vendors</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="horizontalFrame">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="select_vendors_button_fetch">
<property name="text">
<string>Select All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deselect_vendors_button_fetch">
<property name="text">
<string>Deselect All</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QListView" name="vendors_list_view_fetch">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="label_12">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Select Report Types</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="horizontalFrame_2">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="select_report_types_button_fetch">
<property name="text">
<string>Select All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deselect_report_types_button_fetch">
<property name="text">
<string>Deselect All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="report_types_help_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QListView" name="report_types_list_view">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_14">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Date Range</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="spacing">
<number>20</number>
</property>
<item row="3" column="1">
<widget class="QDateEdit" name="end_date_edit_fetch_year">
<property name="dateTime">
<datetime>
<hour>0</hour>
<minute>0</minute>
<second>0</second>
<year>2020</year>
<month>1</month>
<day>1</day>
</datetime>
</property>
<property name="displayFormat">
<string>yyyy</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="begin_month_combo_box"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Begin Date</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QComboBox" name="end_month_combo_box"/>
</item>
<item row="0" column="1">
<widget class="QDateEdit" name="begin_date_edit_fetch_year">
<property name="displayFormat">
<string>yyyy</string>
</property>
<property name="date">
<date>
<year>2020</year>
<month>1</month>
<day>1</day>
</date>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>End Date</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="custom_dir_frame">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_26">
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_38">
<property name="text">
<string>Date range is not a calendar year</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="date_range_help_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>The date range contains months with no available data</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="date_range_help_button2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_41">
<property name="text">
<string>Report(s) will be saved to:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="date_range_help_button3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_39">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="custom_dir_edit"/>
</item>
<item>
<widget class="QPushButton" name="custom_dir_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Change</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QPushButton" name="fetch_advanced_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fetch Selected Reports</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Note: Yearly reports cover all available data for one calender year. Only yearly reports are added to the search database.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>All_reports_edit_fetch</tabstop>
<tabstop>fetch_all_data_button</tabstop>
<tabstop>select_vendors_button_fetch</tabstop>
<tabstop>deselect_vendors_button_fetch</tabstop>
<tabstop>vendors_list_view_fetch</tabstop>
<tabstop>select_report_types_button_fetch</tabstop>
<tabstop>deselect_report_types_button_fetch</tabstop>
<tabstop>report_types_help_button</tabstop>
<tabstop>report_types_list_view</tabstop>
<tabstop>end_date_edit_fetch_year</tabstop>
<tabstop>custom_dir_edit</tabstop>
<tabstop>custom_dir_button</tabstop>
<tabstop>fetch_advanced_button</tabstop>
</tabstops>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

360
ui/FetchSpecialReportsTab.py

@ -0,0 +1,360 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'FetchSpecialReportsTab.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_fetch_special_reports_tab(object):
def setupUi(self, fetch_special_reports_tab):
fetch_special_reports_tab.setObjectName("fetch_special_reports_tab")
fetch_special_reports_tab.resize(1094, 577)
fetch_special_reports_tab.setMinimumSize(QtCore.QSize(800, 0))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/tab_icons/fetch_special_reports_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
fetch_special_reports_tab.setWindowIcon(icon)
self.verticalLayout_2 = QtWidgets.QVBoxLayout(fetch_special_reports_tab)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.frame_2 = QtWidgets.QFrame(fetch_special_reports_tab)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.frame_26 = QtWidgets.QFrame(self.frame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_26.sizePolicy().hasHeightForWidth())
self.frame_26.setSizePolicy(sizePolicy)
self.frame_26.setMinimumSize(QtCore.QSize(200, 0))
self.frame_26.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_26.setObjectName("frame_26")
self.verticalLayout_15 = QtWidgets.QVBoxLayout(self.frame_26)
self.verticalLayout_15.setObjectName("verticalLayout_15")
self.label_21 = QtWidgets.QLabel(self.frame_26)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_21.setFont(font)
self.label_21.setObjectName("label_21")
self.verticalLayout_15.addWidget(self.label_21)
self.frame_32 = QtWidgets.QFrame(self.frame_26)
self.frame_32.setObjectName("frame_32")
self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.frame_32)
self.horizontalLayout_9.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
self.select_vendors_button_special = QtWidgets.QPushButton(self.frame_32)
self.select_vendors_button_special.setObjectName("select_vendors_button_special")
self.horizontalLayout_9.addWidget(self.select_vendors_button_special)
self.deselect_vendors_button_special = QtWidgets.QPushButton(self.frame_32)
self.deselect_vendors_button_special.setObjectName("deselect_vendors_button_special")
self.horizontalLayout_9.addWidget(self.deselect_vendors_button_special)
self.verticalLayout_15.addWidget(self.frame_32)
self.vendors_list_view_special = QtWidgets.QListView(self.frame_26)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
self.vendors_list_view_special.setFont(font)
self.vendors_list_view_special.setAlternatingRowColors(True)
self.vendors_list_view_special.setObjectName("vendors_list_view_special")
self.verticalLayout_15.addWidget(self.vendors_list_view_special)
self.horizontalLayout_2.addWidget(self.frame_26)
self.frame_25 = QtWidgets.QFrame(self.frame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_25.sizePolicy().hasHeightForWidth())
self.frame_25.setSizePolicy(sizePolicy)
self.frame_25.setMinimumSize(QtCore.QSize(180, 0))
self.frame_25.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_25.setObjectName("frame_25")
self.verticalLayout_14 = QtWidgets.QVBoxLayout(self.frame_25)
self.verticalLayout_14.setObjectName("verticalLayout_14")
self.label_20 = QtWidgets.QLabel(self.frame_25)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_20.sizePolicy().hasHeightForWidth())
self.label_20.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_20.setFont(font)
self.label_20.setObjectName("label_20")
self.verticalLayout_14.addWidget(self.label_20)
self.frame_30 = QtWidgets.QFrame(self.frame_25)
self.frame_30.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_30.setObjectName("frame_30")
self.gridLayout_9 = QtWidgets.QGridLayout(self.frame_30)
self.gridLayout_9.setObjectName("gridLayout_9")
self.tr_radio_button = QtWidgets.QRadioButton(self.frame_30)
self.tr_radio_button.setObjectName("tr_radio_button")
self.gridLayout_9.addWidget(self.tr_radio_button, 2, 0, 1, 1, QtCore.Qt.AlignHCenter)
self.pr_radio_button = QtWidgets.QRadioButton(self.frame_30)
self.pr_radio_button.setChecked(True)
self.pr_radio_button.setObjectName("pr_radio_button")
self.gridLayout_9.addWidget(self.pr_radio_button, 0, 0, 1, 1, QtCore.Qt.AlignHCenter)
self.dr_radio_button = QtWidgets.QRadioButton(self.frame_30)
self.dr_radio_button.setObjectName("dr_radio_button")
self.gridLayout_9.addWidget(self.dr_radio_button, 1, 0, 1, 1, QtCore.Qt.AlignHCenter)
self.ir_radio_button = QtWidgets.QRadioButton(self.frame_30)
self.ir_radio_button.setObjectName("ir_radio_button")
self.gridLayout_9.addWidget(self.ir_radio_button, 3, 0, 1, 1, QtCore.Qt.AlignHCenter)
self.verticalLayout_14.addWidget(self.frame_30)
self.horizontalLayout_2.addWidget(self.frame_25)
self.frame_27 = QtWidgets.QFrame(self.frame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_27.sizePolicy().hasHeightForWidth())
self.frame_27.setSizePolicy(sizePolicy)
self.frame_27.setMinimumSize(QtCore.QSize(200, 0))
self.frame_27.setObjectName("frame_27")
self.verticalLayout_16 = QtWidgets.QVBoxLayout(self.frame_27)
self.verticalLayout_16.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_16.setObjectName("verticalLayout_16")
self.frame_15 = QtWidgets.QFrame(self.frame_27)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_15.sizePolicy().hasHeightForWidth())
self.frame_15.setSizePolicy(sizePolicy)
self.frame_15.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_15.setObjectName("frame_15")
self.verticalLayout_22 = QtWidgets.QVBoxLayout(self.frame_15)
self.verticalLayout_22.setObjectName("verticalLayout_22")
self.frame_3 = QtWidgets.QFrame(self.frame_15)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_3.sizePolicy().hasHeightForWidth())
self.frame_3.setSizePolicy(sizePolicy)
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_3.setObjectName("frame_3")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_3)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_14 = QtWidgets.QLabel(self.frame_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_14.sizePolicy().hasHeightForWidth())
self.label_14.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_14.setFont(font)
self.label_14.setObjectName("label_14")
self.horizontalLayout.addWidget(self.label_14)
self.options_help_button = QtWidgets.QPushButton(self.frame_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.options_help_button.sizePolicy().hasHeightForWidth())
self.options_help_button.setSizePolicy(sizePolicy)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/ui/resources/help_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.options_help_button.setIcon(icon1)
self.options_help_button.setObjectName("options_help_button")
self.horizontalLayout.addWidget(self.options_help_button)
self.verticalLayout_22.addWidget(self.frame_3)
self.options_frame = QtWidgets.QFrame(self.frame_15)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.options_frame.sizePolicy().hasHeightForWidth())
self.options_frame.setSizePolicy(sizePolicy)
self.options_frame.setMinimumSize(QtCore.QSize(0, 0))
self.options_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.options_frame.setObjectName("options_frame")
self.gridLayout_6 = QtWidgets.QGridLayout(self.options_frame)
self.gridLayout_6.setObjectName("gridLayout_6")
self.verticalLayout_22.addWidget(self.options_frame)
self.verticalLayout_16.addWidget(self.frame_15)
self.frame_16 = QtWidgets.QFrame(self.frame_27)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_16.sizePolicy().hasHeightForWidth())
self.frame_16.setSizePolicy(sizePolicy)
self.frame_16.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_16.setObjectName("frame_16")
self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_16)
self.verticalLayout.setObjectName("verticalLayout")
self.frame_4 = QtWidgets.QFrame(self.frame_16)
self.frame_4.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame_4.setFrameShadow(QtWidgets.QFrame.Plain)
self.frame_4.setObjectName("frame_4")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.frame_4)
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3.setSpacing(0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label_15 = QtWidgets.QLabel(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_15.sizePolicy().hasHeightForWidth())
self.label_15.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_15.setFont(font)
self.label_15.setObjectName("label_15")
self.horizontalLayout_3.addWidget(self.label_15)
self.date_range_help_button = QtWidgets.QPushButton(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.date_range_help_button.sizePolicy().hasHeightForWidth())
self.date_range_help_button.setSizePolicy(sizePolicy)
self.date_range_help_button.setText("")
self.date_range_help_button.setIcon(icon1)
self.date_range_help_button.setObjectName("date_range_help_button")
self.horizontalLayout_3.addWidget(self.date_range_help_button)
self.verticalLayout.addWidget(self.frame_4)
self.frame = QtWidgets.QFrame(self.frame_16)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
self.frame.setSizePolicy(sizePolicy)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setObjectName("frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
self.gridLayout_2.setSpacing(20)
self.gridLayout_2.setObjectName("gridLayout_2")
self.label_25 = QtWidgets.QLabel(self.frame)
self.label_25.setObjectName("label_25")
self.gridLayout_2.addWidget(self.label_25, 1, 0, 1, 1)
self.begin_date_edit_special_year = QtWidgets.QDateEdit(self.frame)
self.begin_date_edit_special_year.setDateTime(QtCore.QDateTime(QtCore.QDate(2020, 1, 1), QtCore.QTime(0, 0, 0)))
self.begin_date_edit_special_year.setObjectName("begin_date_edit_special_year")
self.gridLayout_2.addWidget(self.begin_date_edit_special_year, 0, 1, 1, 1)
self.label_24 = QtWidgets.QLabel(self.frame)
self.label_24.setObjectName("label_24")
self.gridLayout_2.addWidget(self.label_24, 0, 0, 1, 1)
self.end_date_edit_special_year = QtWidgets.QDateEdit(self.frame)
self.end_date_edit_special_year.setDateTime(QtCore.QDateTime(QtCore.QDate(2020, 1, 1), QtCore.QTime(0, 0, 0)))
self.end_date_edit_special_year.setObjectName("end_date_edit_special_year")
self.gridLayout_2.addWidget(self.end_date_edit_special_year, 1, 1, 1, 1)
self.begin_month_combo_box = QtWidgets.QComboBox(self.frame)
self.begin_month_combo_box.setObjectName("begin_month_combo_box")
self.gridLayout_2.addWidget(self.begin_month_combo_box, 0, 2, 1, 1)
self.end_month_combo_box = QtWidgets.QComboBox(self.frame)
self.end_month_combo_box.setObjectName("end_month_combo_box")
self.gridLayout_2.addWidget(self.end_month_combo_box, 1, 2, 1, 1)
self.verticalLayout.addWidget(self.frame)
self.custom_dir_frame = QtWidgets.QFrame(self.frame_16)
self.custom_dir_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.custom_dir_frame.setObjectName("custom_dir_frame")
self.verticalLayout_26 = QtWidgets.QVBoxLayout(self.custom_dir_frame)
self.verticalLayout_26.setObjectName("verticalLayout_26")
self.frame_5 = QtWidgets.QFrame(self.custom_dir_frame)
self.frame_5.setFrameShape(QtWidgets.QFrame.NoFrame)
self.frame_5.setFrameShadow(QtWidgets.QFrame.Plain)
self.frame_5.setObjectName("frame_5")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.frame_5)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_4.setSpacing(0)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.label_41 = QtWidgets.QLabel(self.frame_5)
self.label_41.setAlignment(QtCore.Qt.AlignCenter)
self.label_41.setObjectName("label_41")
self.horizontalLayout_4.addWidget(self.label_41)
self.custom_dir_help_button = QtWidgets.QPushButton(self.frame_5)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.custom_dir_help_button.sizePolicy().hasHeightForWidth())
self.custom_dir_help_button.setSizePolicy(sizePolicy)
self.custom_dir_help_button.setText("")
self.custom_dir_help_button.setIcon(icon1)
self.custom_dir_help_button.setObjectName("custom_dir_help_button")
self.horizontalLayout_4.addWidget(self.custom_dir_help_button)
self.verticalLayout_26.addWidget(self.frame_5)
self.frame_39 = QtWidgets.QFrame(self.custom_dir_frame)
self.frame_39.setObjectName("frame_39")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.frame_39)
self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.custom_dir_edit = QtWidgets.QLineEdit(self.frame_39)
self.custom_dir_edit.setObjectName("custom_dir_edit")
self.horizontalLayout_7.addWidget(self.custom_dir_edit)
self.custom_dir_button = QtWidgets.QPushButton(self.frame_39)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.custom_dir_button.sizePolicy().hasHeightForWidth())
self.custom_dir_button.setSizePolicy(sizePolicy)
self.custom_dir_button.setObjectName("custom_dir_button")
self.horizontalLayout_7.addWidget(self.custom_dir_button)
self.verticalLayout_26.addWidget(self.frame_39)
self.verticalLayout.addWidget(self.custom_dir_frame)
self.verticalLayout_16.addWidget(self.frame_16)
self.frame_29 = QtWidgets.QFrame(self.frame_27)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_29.sizePolicy().hasHeightForWidth())
self.frame_29.setSizePolicy(sizePolicy)
self.frame_29.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_29.setObjectName("frame_29")
self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_29)
self.gridLayout_8.setObjectName("gridLayout_8")
self.fetch_special_data_button = QtWidgets.QPushButton(self.frame_29)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.fetch_special_data_button.sizePolicy().hasHeightForWidth())
self.fetch_special_data_button.setSizePolicy(sizePolicy)
self.fetch_special_data_button.setMaximumSize(QtCore.QSize(180, 16777215))
self.fetch_special_data_button.setObjectName("fetch_special_data_button")
self.gridLayout_8.addWidget(self.fetch_special_data_button, 0, 0, 1, 1)
self.verticalLayout_16.addWidget(self.frame_29)
self.horizontalLayout_2.addWidget(self.frame_27)
self.verticalLayout_2.addWidget(self.frame_2)
self.label = QtWidgets.QLabel(fetch_special_reports_tab)
self.label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label.setObjectName("label")
self.verticalLayout_2.addWidget(self.label)
self.retranslateUi(fetch_special_reports_tab)
QtCore.QMetaObject.connectSlotsByName(fetch_special_reports_tab)
fetch_special_reports_tab.setTabOrder(self.select_vendors_button_special, self.deselect_vendors_button_special)
fetch_special_reports_tab.setTabOrder(self.deselect_vendors_button_special, self.vendors_list_view_special)
fetch_special_reports_tab.setTabOrder(self.vendors_list_view_special, self.pr_radio_button)
fetch_special_reports_tab.setTabOrder(self.pr_radio_button, self.dr_radio_button)
fetch_special_reports_tab.setTabOrder(self.dr_radio_button, self.tr_radio_button)
fetch_special_reports_tab.setTabOrder(self.tr_radio_button, self.ir_radio_button)
fetch_special_reports_tab.setTabOrder(self.ir_radio_button, self.options_frame)
fetch_special_reports_tab.setTabOrder(self.options_frame, self.begin_date_edit_special_year)
fetch_special_reports_tab.setTabOrder(self.begin_date_edit_special_year, self.end_date_edit_special_year)
fetch_special_reports_tab.setTabOrder(self.end_date_edit_special_year, self.fetch_special_data_button)
def retranslateUi(self, fetch_special_reports_tab):
_translate = QtCore.QCoreApplication.translate
fetch_special_reports_tab.setWindowTitle(_translate("fetch_special_reports_tab", "Fetch Special Reports"))
self.label_21.setText(_translate("fetch_special_reports_tab", "Select Vendors"))
self.select_vendors_button_special.setText(_translate("fetch_special_reports_tab", "Select All"))
self.deselect_vendors_button_special.setText(_translate("fetch_special_reports_tab", "Deselect All"))
self.label_20.setText(_translate("fetch_special_reports_tab", "Select Report Type"))
self.tr_radio_button.setText(_translate("fetch_special_reports_tab", "TR"))
self.pr_radio_button.setText(_translate("fetch_special_reports_tab", "PR"))
self.dr_radio_button.setText(_translate("fetch_special_reports_tab", "DR"))
self.ir_radio_button.setText(_translate("fetch_special_reports_tab", "IR"))
self.label_14.setText(_translate("fetch_special_reports_tab", "Options"))
self.label_15.setText(_translate("fetch_special_reports_tab", "Date Range"))
self.label_25.setText(_translate("fetch_special_reports_tab", "End Date"))
self.begin_date_edit_special_year.setDisplayFormat(_translate("fetch_special_reports_tab", "yyyy"))
self.label_24.setText(_translate("fetch_special_reports_tab", "Begin Date"))
self.end_date_edit_special_year.setDisplayFormat(_translate("fetch_special_reports_tab", "yyyy"))
self.label_41.setText(_translate("fetch_special_reports_tab", "Report(s) will be saved to:"))
self.custom_dir_button.setText(_translate("fetch_special_reports_tab", "Change"))
self.fetch_special_data_button.setText(_translate("fetch_special_reports_tab", "Fetch Special Report"))
self.label.setText(_translate("fetch_special_reports_tab", "Note: Special reports are not added to the search database."))
import Resources_rc

633
ui/FetchSpecialReportsTab.ui

@ -0,0 +1,633 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>fetch_special_reports_tab</class>
<widget class="QWidget" name="fetch_special_reports_tab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1094</width>
<height>577</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Fetch Special Reports</string>
</property>
<property name="windowIcon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/tab_icons/fetch_special_reports_icon.png</normaloff>:/ui/resources/tab_icons/fetch_special_reports_icon.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QFrame" name="frame_26">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_15">
<item>
<widget class="QLabel" name="label_21">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Select Vendors</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_32">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="select_vendors_button_special">
<property name="text">
<string>Select All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deselect_vendors_button_special">
<property name="text">
<string>Deselect All</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QListView" name="vendors_list_view_special">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_25">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>180</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_14">
<item>
<widget class="QLabel" name="label_20">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Select Report Type</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_30">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout_9">
<item row="2" column="0" alignment="Qt::AlignHCenter">
<widget class="QRadioButton" name="tr_radio_button">
<property name="text">
<string>TR</string>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignHCenter">
<widget class="QRadioButton" name="pr_radio_button">
<property name="text">
<string>PR</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" alignment="Qt::AlignHCenter">
<widget class="QRadioButton" name="dr_radio_button">
<property name="text">
<string>DR</string>
</property>
</widget>
</item>
<item row="3" column="0" alignment="Qt::AlignHCenter">
<widget class="QRadioButton" name="ir_radio_button">
<property name="text">
<string>IR</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_27">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_16">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_15">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_22">
<item>
<widget class="QFrame" name="frame_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_14">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Options</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="options_help_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="options_frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout_6"/>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_16">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame_4">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_15">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Date Range</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="date_range_help_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="spacing">
<number>20</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>End Date</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDateEdit" name="begin_date_edit_special_year">
<property name="dateTime">
<datetime>
<hour>0</hour>
<minute>0</minute>
<second>0</second>
<year>2020</year>
<month>1</month>
<day>1</day>
</datetime>
</property>
<property name="displayFormat">
<string>yyyy</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Begin Date</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDateEdit" name="end_date_edit_special_year">
<property name="dateTime">
<datetime>
<hour>0</hour>
<minute>0</minute>
<second>0</second>
<year>2020</year>
<month>1</month>
<day>1</day>
</datetime>
</property>
<property name="displayFormat">
<string>yyyy</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="begin_month_combo_box"/>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="end_month_combo_box"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="custom_dir_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_26">
<item>
<widget class="QFrame" name="frame_5">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_41">
<property name="text">
<string>Report(s) will be saved to:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="custom_dir_help_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_39">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="custom_dir_edit"/>
</item>
<item>
<widget class="QPushButton" name="custom_dir_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Change</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_29">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
<widget class="QPushButton" name="fetch_special_data_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>180</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Fetch Special Report</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Note: Special reports are not added to the search database.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>select_vendors_button_special</tabstop>
<tabstop>deselect_vendors_button_special</tabstop>
<tabstop>vendors_list_view_special</tabstop>
<tabstop>pr_radio_button</tabstop>
<tabstop>dr_radio_button</tabstop>
<tabstop>tr_radio_button</tabstop>
<tabstop>ir_radio_button</tabstop>
<tabstop>options_frame</tabstop>
<tabstop>begin_date_edit_special_year</tabstop>
<tabstop>end_date_edit_special_year</tabstop>
<tabstop>fetch_special_data_button</tabstop>
</tabstops>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

208
ui/ImportReportTab.py

@ -0,0 +1,208 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ImportReportTab.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_import_report_tab(object):
def setupUi(self, import_report_tab):
import_report_tab.setObjectName("import_report_tab")
import_report_tab.resize(1008, 530)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/tab_icons/import_report_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
import_report_tab.setWindowIcon(icon)
self.verticalLayout = QtWidgets.QVBoxLayout(import_report_tab)
self.verticalLayout.setObjectName("verticalLayout")
self.frame = QtWidgets.QFrame(import_report_tab)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setObjectName("frame")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.frame_21 = QtWidgets.QFrame(self.frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_21.sizePolicy().hasHeightForWidth())
self.frame_21.setSizePolicy(sizePolicy)
self.frame_21.setMinimumSize(QtCore.QSize(200, 0))
self.frame_21.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_21.setObjectName("frame_21")
self.verticalLayout_12 = QtWidgets.QVBoxLayout(self.frame_21)
self.verticalLayout_12.setObjectName("verticalLayout_12")
self.label_18 = QtWidgets.QLabel(self.frame_21)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.label_18.setFont(font)
self.label_18.setObjectName("label_18")
self.verticalLayout_12.addWidget(self.label_18)
self.vendors_list_view_import = QtWidgets.QListView(self.frame_21)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
self.vendors_list_view_import.setFont(font)
self.vendors_list_view_import.setAlternatingRowColors(True)
self.vendors_list_view_import.setObjectName("vendors_list_view_import")
self.verticalLayout_12.addWidget(self.vendors_list_view_import)
self.horizontalLayout_2.addWidget(self.frame_21)
self.frame_20 = QtWidgets.QFrame(self.frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_20.sizePolicy().hasHeightForWidth())
self.frame_20.setSizePolicy(sizePolicy)
self.frame_20.setMinimumSize(QtCore.QSize(200, 0))
self.frame_20.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_20.setObjectName("frame_20")
self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.frame_20)
self.verticalLayout_11.setObjectName("verticalLayout_11")
self.label_17 = QtWidgets.QLabel(self.frame_20)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.label_17.setFont(font)
self.label_17.setObjectName("label_17")
self.verticalLayout_11.addWidget(self.label_17)
self.report_types_list_view_import = QtWidgets.QListView(self.frame_20)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
self.report_types_list_view_import.setFont(font)
self.report_types_list_view_import.setAlternatingRowColors(True)
self.report_types_list_view_import.setObjectName("report_types_list_view_import")
self.verticalLayout_11.addWidget(self.report_types_list_view_import)
self.horizontalLayout_2.addWidget(self.frame_20)
self.frame_22 = QtWidgets.QFrame(self.frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_22.sizePolicy().hasHeightForWidth())
self.frame_22.setSizePolicy(sizePolicy)
self.frame_22.setMinimumSize(QtCore.QSize(200, 0))
self.frame_22.setObjectName("frame_22")
self.verticalLayout_13 = QtWidgets.QVBoxLayout(self.frame_22)
self.verticalLayout_13.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_13.setObjectName("verticalLayout_13")
self.frame_17 = QtWidgets.QFrame(self.frame_22)
self.frame_17.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_17.setObjectName("frame_17")
self.verticalLayout_24 = QtWidgets.QVBoxLayout(self.frame_17)
self.verticalLayout_24.setObjectName("verticalLayout_24")
self.label_16 = QtWidgets.QLabel(self.frame_17)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_16.sizePolicy().hasHeightForWidth())
self.label_16.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_16.setFont(font)
self.label_16.setObjectName("label_16")
self.verticalLayout_24.addWidget(self.label_16)
self.frame_19 = QtWidgets.QFrame(self.frame_17)
self.frame_19.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_19.setObjectName("frame_19")
self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.frame_19)
self.horizontalLayout_13.setObjectName("horizontalLayout_13")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_13.addItem(spacerItem)
self.label_19 = QtWidgets.QLabel(self.frame_19)
self.label_19.setMinimumSize(QtCore.QSize(100, 0))
self.label_19.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_19.setObjectName("label_19")
self.horizontalLayout_13.addWidget(self.label_19)
self.report_year_date_edit = QtWidgets.QDateEdit(self.frame_19)
self.report_year_date_edit.setObjectName("report_year_date_edit")
self.horizontalLayout_13.addWidget(self.report_year_date_edit)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_13.addItem(spacerItem1)
self.verticalLayout_24.addWidget(self.frame_19)
self.verticalLayout_13.addWidget(self.frame_17)
self.frame_18 = QtWidgets.QFrame(self.frame_22)
self.frame_18.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_18.setObjectName("frame_18")
self.verticalLayout_25 = QtWidgets.QVBoxLayout(self.frame_18)
self.verticalLayout_25.setObjectName("verticalLayout_25")
self.label_36 = QtWidgets.QLabel(self.frame_18)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_36.sizePolicy().hasHeightForWidth())
self.label_36.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.label_36.setFont(font)
self.label_36.setObjectName("label_36")
self.verticalLayout_25.addWidget(self.label_36)
self.frame_38 = QtWidgets.QFrame(self.frame_18)
self.frame_38.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_38.setObjectName("frame_38")
self.horizontalLayout_15 = QtWidgets.QHBoxLayout(self.frame_38)
self.horizontalLayout_15.setObjectName("horizontalLayout_15")
self.select_file_button = QtWidgets.QPushButton(self.frame_38)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.select_file_button.sizePolicy().hasHeightForWidth())
self.select_file_button.setSizePolicy(sizePolicy)
self.select_file_button.setObjectName("select_file_button")
self.horizontalLayout_15.addWidget(self.select_file_button)
self.selected_file_edit = QtWidgets.QLineEdit(self.frame_38)
self.selected_file_edit.setReadOnly(True)
self.selected_file_edit.setObjectName("selected_file_edit")
self.horizontalLayout_15.addWidget(self.selected_file_edit)
self.verticalLayout_25.addWidget(self.frame_38)
self.verticalLayout_13.addWidget(self.frame_18)
self.frame_24 = QtWidgets.QFrame(self.frame_22)
self.frame_24.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_24.setObjectName("frame_24")
self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_24)
self.gridLayout_7.setObjectName("gridLayout_7")
self.import_report_button = QtWidgets.QPushButton(self.frame_24)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.import_report_button.sizePolicy().hasHeightForWidth())
self.import_report_button.setSizePolicy(sizePolicy)
self.import_report_button.setMaximumSize(QtCore.QSize(180, 16777215))
self.import_report_button.setObjectName("import_report_button")
self.gridLayout_7.addWidget(self.import_report_button, 0, 0, 1, 1)
self.verticalLayout_13.addWidget(self.frame_24)
self.horizontalLayout_2.addWidget(self.frame_22)
self.verticalLayout.addWidget(self.frame)
self.label = QtWidgets.QLabel(import_report_tab)
self.label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.retranslateUi(import_report_tab)
QtCore.QMetaObject.connectSlotsByName(import_report_tab)
import_report_tab.setTabOrder(self.vendors_list_view_import, self.report_types_list_view_import)
import_report_tab.setTabOrder(self.report_types_list_view_import, self.report_year_date_edit)
import_report_tab.setTabOrder(self.report_year_date_edit, self.selected_file_edit)
import_report_tab.setTabOrder(self.selected_file_edit, self.import_report_button)
def retranslateUi(self, import_report_tab):
_translate = QtCore.QCoreApplication.translate
import_report_tab.setWindowTitle(_translate("import_report_tab", "Import Report"))
self.label_18.setText(_translate("import_report_tab", "Select Vendor"))
self.label_17.setText(_translate("import_report_tab", "Select Report Type"))
self.label_16.setText(_translate("import_report_tab", "Date"))
self.label_19.setText(_translate("import_report_tab", "Report Year"))
self.report_year_date_edit.setDisplayFormat(_translate("import_report_tab", "yyyy"))
self.label_36.setText(_translate("import_report_tab", "Target Report File"))
self.select_file_button.setText(_translate("import_report_tab", "Select File"))
self.import_report_button.setText(_translate("import_report_tab", "Import Selected Report"))
self.label.setText(_translate("import_report_tab", "Note: Only yearly reports (all available data for one calender year) should be imported. Imported reports are added to the search database."))
import Resources_rc

352
ui/ImportReportTab.ui

@ -0,0 +1,352 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>import_report_tab</class>
<widget class="QWidget" name="import_report_tab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1008</width>
<height>530</height>
</rect>
</property>
<property name="windowTitle">
<string>Import Report</string>
</property>
<property name="windowIcon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/tab_icons/import_report_icon.png</normaloff>:/ui/resources/tab_icons/import_report_icon.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QFrame" name="frame_21">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<widget class="QLabel" name="label_18">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Select Vendor</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="vendors_list_view_import">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_20">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QLabel" name="label_17">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Select Report Type</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="report_types_list_view_import">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_22">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_17">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_24">
<item>
<widget class="QLabel" name="label_16">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Date</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_19">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_19">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Report Year</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDateEdit" name="report_year_date_edit">
<property name="displayFormat">
<string>yyyy</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_18">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_25">
<item>
<widget class="QLabel" name="label_36">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Target Report File</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_38">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QPushButton" name="select_file_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Select File</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="selected_file_edit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_24">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QPushButton" name="import_report_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>180</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Import Selected Report</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Note: Only yearly reports (all available data for one calender year) should be imported. Imported reports are added to the search database.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>vendors_list_view_import</tabstop>
<tabstop>report_types_list_view_import</tabstop>
<tabstop>report_year_date_edit</tabstop>
<tabstop>selected_file_edit</tabstop>
<tabstop>import_report_button</tabstop>
</tabstops>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

58
ui/MainWindow.py

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_mainWindow(object):
def setupUi(self, mainWindow):
mainWindow.setObjectName("mainWindow")
mainWindow.resize(1200, 721)
mainWindow.setMinimumSize(QtCore.QSize(1200, 640))
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
mainWindow.setFont(font)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/main_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
mainWindow.setWindowIcon(icon)
self.centralwidget = QtWidgets.QWidget(mainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setContentsMargins(-1, -1, -1, 0)
self.gridLayout.setObjectName("gridLayout")
self.tab_widget = QtWidgets.QTabWidget(self.centralwidget)
self.tab_widget.setEnabled(True)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tab_widget.sizePolicy().hasHeightForWidth())
self.tab_widget.setSizePolicy(sizePolicy)
self.tab_widget.setMaximumSize(QtCore.QSize(16777215, 16777215))
self.tab_widget.setTabPosition(QtWidgets.QTabWidget.North)
self.tab_widget.setElideMode(QtCore.Qt.ElideNone)
self.tab_widget.setObjectName("tab_widget")
self.gridLayout.addWidget(self.tab_widget, 1, 0, 1, 1)
mainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(mainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 21))
self.menubar.setObjectName("menubar")
mainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(mainWindow)
self.statusbar.setObjectName("statusbar")
mainWindow.setStatusBar(self.statusbar)
self.retranslateUi(mainWindow)
self.tab_widget.setCurrentIndex(-1)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
def retranslateUi(self, mainWindow):
_translate = QtCore.QCoreApplication.translate
mainWindow.setWindowTitle(_translate("mainWindow", "COUNTER 5 Report Tool"))
import Resources_rc

83
ui/MainWindow.ui

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>mainWindow</class>
<widget class="QMainWindow" name="mainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1200</width>
<height>721</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>1200</width>
<height>640</height>
</size>
</property>
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="windowTitle">
<string>COUNTER 5 Report Tool</string>
</property>
<property name="windowIcon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/main_icon.png</normaloff>:/ui/resources/main_icon.png</iconset>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="0">
<widget class="QTabWidget" name="tab_widget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
<property name="elideMode">
<enum>Qt::ElideNone</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1200</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

262
ui/ManageVendorsTab.py

@ -0,0 +1,262 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ManageVendorsTab.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_manage_vendors_tab(object):
def setupUi(self, manage_vendors_tab):
manage_vendors_tab.setObjectName("manage_vendors_tab")
manage_vendors_tab.resize(807, 642)
font = QtGui.QFont()
font.setFamily("Segoe UI")
manage_vendors_tab.setFont(font)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/tab_icons/manage_vendors_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
manage_vendors_tab.setWindowIcon(icon)
self.horizontalLayout = QtWidgets.QHBoxLayout(manage_vendors_tab)
self.horizontalLayout.setObjectName("horizontalLayout")
self.frame_12 = QtWidgets.QFrame(manage_vendors_tab)
self.frame_12.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_12.setObjectName("frame_12")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.frame_12)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.label_13 = QtWidgets.QLabel(self.frame_12)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.label_13.setFont(font)
self.label_13.setObjectName("label_13")
self.verticalLayout_6.addWidget(self.label_13)
self.vendorsListView = QtWidgets.QListView(self.frame_12)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
self.vendorsListView.setFont(font)
self.vendorsListView.setAlternatingRowColors(True)
self.vendorsListView.setObjectName("vendorsListView")
self.verticalLayout_6.addWidget(self.vendorsListView)
self.frame_2 = QtWidgets.QFrame(self.frame_12)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setObjectName("frame_2")
self.gridLayout_3 = QtWidgets.QGridLayout(self.frame_2)
self.gridLayout_3.setObjectName("gridLayout_3")
self.importVendorsButton = QtWidgets.QPushButton(self.frame_2)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/ui/resources/import_vendors_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.importVendorsButton.setIcon(icon1)
self.importVendorsButton.setObjectName("importVendorsButton")
self.gridLayout_3.addWidget(self.importVendorsButton, 0, 1, 1, 1)
self.addVendorButton = QtWidgets.QPushButton(self.frame_2)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/ui/resources/add_vendor_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.addVendorButton.setIcon(icon2)
self.addVendorButton.setObjectName("addVendorButton")
self.gridLayout_3.addWidget(self.addVendorButton, 0, 0, 1, 1)
self.exportVendorsButton = QtWidgets.QPushButton(self.frame_2)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/ui/resources/export_vendors_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.exportVendorsButton.setIcon(icon3)
self.exportVendorsButton.setObjectName("exportVendorsButton")
self.gridLayout_3.addWidget(self.exportVendorsButton, 0, 2, 1, 1)
self.verticalLayout_6.addWidget(self.frame_2)
self.horizontalLayout.addWidget(self.frame_12)
self.frame_8 = QtWidgets.QFrame(manage_vendors_tab)
self.frame_8.setObjectName("frame_8")
self.horizontalLayout_2 = QtWidgets.QVBoxLayout(self.frame_8)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.frame = QtWidgets.QFrame(self.frame_8)
self.frame.setEnabled(True)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setObjectName("frame")
self.verticalLayout = QtWidgets.QVBoxLayout(self.frame)
self.verticalLayout.setObjectName("verticalLayout")
self.label_7 = QtWidgets.QLabel(self.frame)
self.label_7.setEnabled(True)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.label_7.setFont(font)
self.label_7.setFrameShape(QtWidgets.QFrame.NoFrame)
self.label_7.setObjectName("label_7")
self.verticalLayout.addWidget(self.label_7)
self.edit_vendor_details_frame = QtWidgets.QFrame(self.frame)
self.edit_vendor_details_frame.setObjectName("edit_vendor_details_frame")
self.gridLayout_5 = QtWidgets.QGridLayout(self.edit_vendor_details_frame)
self.gridLayout_5.setSpacing(20)
self.gridLayout_5.setObjectName("gridLayout_5")
self.name_validation_label = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.name_validation_label.setObjectName("name_validation_label")
self.gridLayout_5.addWidget(self.name_validation_label, 1, 1, 1, 1)
self.label_28 = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.label_28.setObjectName("label_28")
self.gridLayout_5.addWidget(self.label_28, 11, 0, 1, 1, QtCore.Qt.AlignTop)
self.descriptionEdit = QtWidgets.QPlainTextEdit(self.edit_vendor_details_frame)
self.descriptionEdit.setAutoFillBackground(False)
self.descriptionEdit.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.descriptionEdit.setFrameShadow(QtWidgets.QFrame.Sunken)
self.descriptionEdit.setTabChangesFocus(False)
self.descriptionEdit.setPlainText("")
self.descriptionEdit.setBackgroundVisible(False)
self.descriptionEdit.setObjectName("descriptionEdit")
self.gridLayout_5.addWidget(self.descriptionEdit, 11, 1, 1, 1)
self.nameEdit = QtWidgets.QLineEdit(self.edit_vendor_details_frame)
self.nameEdit.setObjectName("nameEdit")
self.gridLayout_5.addWidget(self.nameEdit, 0, 1, 1, 1)
self.url_validation_label = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.url_validation_label.setObjectName("url_validation_label")
self.gridLayout_5.addWidget(self.url_validation_label, 3, 1, 1, 1)
self.companiesText = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.companiesText.setObjectName("companiesText")
self.gridLayout_5.addWidget(self.companiesText, 12, 0, 1, 1, QtCore.Qt.AlignTop)
self.label_4 = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.label_4.setObjectName("label_4")
self.gridLayout_5.addWidget(self.label_4, 7, 0, 1, 1)
self.frame_3 = QtWidgets.QFrame(self.edit_vendor_details_frame)
self.frame_3.setObjectName("frame_3")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.frame_3)
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.non_Sushi_check_box = QtWidgets.QCheckBox(self.frame_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.non_Sushi_check_box.sizePolicy().hasHeightForWidth())
self.non_Sushi_check_box.setSizePolicy(sizePolicy)
self.non_Sushi_check_box.setText("")
self.non_Sushi_check_box.setObjectName("non_Sushi_check_box")
self.horizontalLayout_3.addWidget(self.non_Sushi_check_box)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem)
self.non_sushi_help_button = QtWidgets.QPushButton(self.frame_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.non_sushi_help_button.sizePolicy().hasHeightForWidth())
self.non_sushi_help_button.setSizePolicy(sizePolicy)
self.non_sushi_help_button.setText("")
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/ui/resources/help_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.non_sushi_help_button.setIcon(icon4)
self.non_sushi_help_button.setObjectName("non_sushi_help_button")
self.horizontalLayout_3.addWidget(self.non_sushi_help_button)
self.gridLayout_5.addWidget(self.frame_3, 10, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.label_3.setObjectName("label_3")
self.gridLayout_5.addWidget(self.label_3, 2, 0, 1, 1)
self.baseUrlEdit = QtWidgets.QLineEdit(self.edit_vendor_details_frame)
self.baseUrlEdit.setObjectName("baseUrlEdit")
self.gridLayout_5.addWidget(self.baseUrlEdit, 2, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.label_2.setObjectName("label_2")
self.gridLayout_5.addWidget(self.label_2, 4, 0, 1, 1)
self.apiKeyEdit = QtWidgets.QLineEdit(self.edit_vendor_details_frame)
self.apiKeyEdit.setObjectName("apiKeyEdit")
self.gridLayout_5.addWidget(self.apiKeyEdit, 8, 1, 1, 1)
self.label_5 = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.label_5.setObjectName("label_5")
self.gridLayout_5.addWidget(self.label_5, 8, 0, 1, 1)
self.label = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.label.setObjectName("label")
self.gridLayout_5.addWidget(self.label, 0, 0, 1, 1)
self.companiesEdit = QtWidgets.QPlainTextEdit(self.edit_vendor_details_frame)
self.companiesEdit.setObjectName("companiesEdit")
self.gridLayout_5.addWidget(self.companiesEdit, 12, 1, 1, 1)
self.platformEdit = QtWidgets.QLineEdit(self.edit_vendor_details_frame)
self.platformEdit.setObjectName("platformEdit")
self.gridLayout_5.addWidget(self.platformEdit, 9, 1, 1, 1)
self.label_39 = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.label_39.setObjectName("label_39")
self.gridLayout_5.addWidget(self.label_39, 10, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(self.edit_vendor_details_frame)
self.label_6.setObjectName("label_6")
self.gridLayout_5.addWidget(self.label_6, 9, 0, 1, 1)
self.requestorIdEdit = QtWidgets.QLineEdit(self.edit_vendor_details_frame)
self.requestorIdEdit.setObjectName("requestorIdEdit")
self.gridLayout_5.addWidget(self.requestorIdEdit, 7, 1, 1, 1)
self.customerIdEdit = QtWidgets.QLineEdit(self.edit_vendor_details_frame)
self.customerIdEdit.setObjectName("customerIdEdit")
self.gridLayout_5.addWidget(self.customerIdEdit, 4, 1, 1, 1)
self.verticalLayout.addWidget(self.edit_vendor_details_frame)
self.edit_vendor_options_frame = QtWidgets.QFrame(self.frame)
self.edit_vendor_options_frame.setEnabled(False)
self.edit_vendor_options_frame.setObjectName("edit_vendor_options_frame")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.edit_vendor_options_frame)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.saveVendorChangesButton = QtWidgets.QPushButton(self.edit_vendor_options_frame)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/ui/resources/save_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.saveVendorChangesButton.setIcon(icon5)
self.saveVendorChangesButton.setDefault(False)
self.saveVendorChangesButton.setFlat(False)
self.saveVendorChangesButton.setObjectName("saveVendorChangesButton")
self.horizontalLayout_5.addWidget(self.saveVendorChangesButton)
self.undoVendorChangesButton = QtWidgets.QPushButton(self.edit_vendor_options_frame)
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(":/ui/resources/undo_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.undoVendorChangesButton.setIcon(icon6)
self.undoVendorChangesButton.setObjectName("undoVendorChangesButton")
self.horizontalLayout_5.addWidget(self.undoVendorChangesButton)
self.removeVendorButton = QtWidgets.QPushButton(self.edit_vendor_options_frame)
icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap(":/ui/resources/remove_vendor_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.removeVendorButton.setIcon(icon7)
self.removeVendorButton.setObjectName("removeVendorButton")
self.horizontalLayout_5.addWidget(self.removeVendorButton)
self.verticalLayout.addWidget(self.edit_vendor_options_frame)
self.horizontalLayout_2.addWidget(self.frame)
self.horizontalLayout.addWidget(self.frame_8)
self.retranslateUi(manage_vendors_tab)
QtCore.QMetaObject.connectSlotsByName(manage_vendors_tab)
manage_vendors_tab.setTabOrder(self.vendorsListView, self.addVendorButton)
manage_vendors_tab.setTabOrder(self.addVendorButton, self.importVendorsButton)
manage_vendors_tab.setTabOrder(self.importVendorsButton, self.exportVendorsButton)
manage_vendors_tab.setTabOrder(self.exportVendorsButton, self.nameEdit)
manage_vendors_tab.setTabOrder(self.nameEdit, self.baseUrlEdit)
manage_vendors_tab.setTabOrder(self.baseUrlEdit, self.customerIdEdit)
manage_vendors_tab.setTabOrder(self.customerIdEdit, self.requestorIdEdit)
manage_vendors_tab.setTabOrder(self.requestorIdEdit, self.apiKeyEdit)
manage_vendors_tab.setTabOrder(self.apiKeyEdit, self.platformEdit)
manage_vendors_tab.setTabOrder(self.platformEdit, self.non_Sushi_check_box)
manage_vendors_tab.setTabOrder(self.non_Sushi_check_box, self.non_sushi_help_button)
manage_vendors_tab.setTabOrder(self.non_sushi_help_button, self.descriptionEdit)
manage_vendors_tab.setTabOrder(self.descriptionEdit, self.companiesEdit)
manage_vendors_tab.setTabOrder(self.companiesEdit, self.saveVendorChangesButton)
manage_vendors_tab.setTabOrder(self.saveVendorChangesButton, self.undoVendorChangesButton)
manage_vendors_tab.setTabOrder(self.undoVendorChangesButton, self.removeVendorButton)
def retranslateUi(self, manage_vendors_tab):
_translate = QtCore.QCoreApplication.translate
manage_vendors_tab.setWindowTitle(_translate("manage_vendors_tab", "Manage Vendors"))
self.label_13.setText(_translate("manage_vendors_tab", "Select Vendor"))
self.importVendorsButton.setText(_translate("manage_vendors_tab", "Import Vendors"))
self.addVendorButton.setText(_translate("manage_vendors_tab", "Add New Vendor"))
self.exportVendorsButton.setText(_translate("manage_vendors_tab", "Export Vendors"))
self.label_7.setText(_translate("manage_vendors_tab", "Edit Vendor"))
self.name_validation_label.setText(_translate("manage_vendors_tab", "Validation label"))
self.label_28.setText(_translate("manage_vendors_tab", "Description"))
self.url_validation_label.setText(_translate("manage_vendors_tab", "Validation label"))
self.companiesText.setText(_translate("manage_vendors_tab", "Third party provider"))
self.label_4.setText(_translate("manage_vendors_tab", "Requestor ID"))
self.label_3.setText(_translate("manage_vendors_tab", "Base URL"))
self.label_2.setText(_translate("manage_vendors_tab", "Customer ID"))
self.label_5.setText(_translate("manage_vendors_tab", "API Key"))
self.label.setText(_translate("manage_vendors_tab", "Name"))
self.label_39.setText(_translate("manage_vendors_tab", "Non-SUSHI Vendor"))
self.label_6.setText(_translate("manage_vendors_tab", "Platform"))
self.saveVendorChangesButton.setText(_translate("manage_vendors_tab", "Save Changes"))
self.undoVendorChangesButton.setText(_translate("manage_vendors_tab", "Undo Changes"))
self.removeVendorButton.setText(_translate("manage_vendors_tab", "Remove Vendor"))
import Resources_rc

419
ui/ManageVendorsTab.ui

@ -0,0 +1,419 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>manage_vendors_tab</class>
<widget class="QWidget" name="manage_vendors_tab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>807</width>
<height>642</height>
</rect>
</property>
<property name="font">
<font>
<family>Segoe UI</family>
</font>
</property>
<property name="windowTitle">
<string>Manage Vendors</string>
</property>
<property name="windowIcon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/tab_icons/manage_vendors_icon.png</normaloff>:/ui/resources/tab_icons/manage_vendors_icon.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QFrame" name="frame_12">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QLabel" name="label_13">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Select Vendor</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="vendorsListView">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="1">
<widget class="QPushButton" name="importVendorsButton">
<property name="text">
<string>Import Vendors</string>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/import_vendors_icon.png</normaloff>:/ui/resources/import_vendors_icon.png</iconset>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="addVendorButton">
<property name="text">
<string>Add New Vendor</string>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/add_vendor_icon.png</normaloff>:/ui/resources/add_vendor_icon.png</iconset>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="exportVendorsButton">
<property name="text">
<string>Export Vendors</string>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/export_vendors_icon.png</normaloff>:/ui/resources/export_vendors_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_8">
<layout class="QVBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame">
<property name="enabled">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_7">
<property name="enabled">
<bool>true</bool>
</property>
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string>Edit Vendor</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="edit_vendor_details_frame">
<layout class="QGridLayout" name="gridLayout_5">
<property name="spacing">
<number>20</number>
</property>
<item row="1" column="1">
<widget class="QLabel" name="name_validation_label">
<property name="text">
<string>Validation label</string>
</property>
</widget>
</item>
<item row="11" column="0" alignment="Qt::AlignTop">
<widget class="QLabel" name="label_28">
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QPlainTextEdit" name="descriptionEdit">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="tabChangesFocus">
<bool>false</bool>
</property>
<property name="plainText">
<string/>
</property>
<property name="backgroundVisible">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="nameEdit"/>
</item>
<item row="3" column="1">
<widget class="QLabel" name="url_validation_label">
<property name="text">
<string>Validation label</string>
</property>
</widget>
</item>
<item row="12" column="0" alignment="Qt::AlignTop">
<widget class="QLabel" name="companiesText">
<property name="text">
<string>Third party provider</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Requestor ID</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QFrame" name="frame_3">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="non_Sushi_check_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="non_sushi_help_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Base URL</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="baseUrlEdit"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Customer ID</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="apiKeyEdit"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>API Key</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QPlainTextEdit" name="companiesEdit"/>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="platformEdit"/>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Non-SUSHI Vendor</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Platform</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="requestorIdEdit"/>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="customerIdEdit"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="edit_vendor_options_frame">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QPushButton" name="saveVendorChangesButton">
<property name="text">
<string>Save Changes</string>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/save_icon.png</normaloff>:/ui/resources/save_icon.png</iconset>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="undoVendorChangesButton">
<property name="text">
<string>Undo Changes</string>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/undo_icon.png</normaloff>:/ui/resources/undo_icon.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeVendorButton">
<property name="text">
<string>Remove Vendor</string>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/remove_vendor_icon.png</normaloff>:/ui/resources/remove_vendor_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>vendorsListView</tabstop>
<tabstop>addVendorButton</tabstop>
<tabstop>importVendorsButton</tabstop>
<tabstop>exportVendorsButton</tabstop>
<tabstop>nameEdit</tabstop>
<tabstop>baseUrlEdit</tabstop>
<tabstop>customerIdEdit</tabstop>
<tabstop>requestorIdEdit</tabstop>
<tabstop>apiKeyEdit</tabstop>
<tabstop>platformEdit</tabstop>
<tabstop>non_Sushi_check_box</tabstop>
<tabstop>non_sushi_help_button</tabstop>
<tabstop>descriptionEdit</tabstop>
<tabstop>companiesEdit</tabstop>
<tabstop>saveVendorChangesButton</tabstop>
<tabstop>undoVendorChangesButton</tabstop>
<tabstop>removeVendorButton</tabstop>
</tabstops>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

37
ui/MessageDialog.py

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MessageDialog.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_message_dialog(object):
def setupUi(self, message_dialog):
message_dialog.setObjectName("message_dialog")
message_dialog.resize(400, 60)
self.verticalLayout = QtWidgets.QVBoxLayout(message_dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.message_label = QtWidgets.QLabel(message_dialog)
font = QtGui.QFont()
font.setPointSize(9)
self.message_label.setFont(font)
self.message_label.setAlignment(QtCore.Qt.AlignCenter)
self.message_label.setObjectName("message_label")
self.verticalLayout.addWidget(self.message_label)
self.buttonBox = QtWidgets.QDialogButtonBox(message_dialog)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.buttonBox.accepted.connect(message_dialog.accept)
self.retranslateUi(message_dialog)
QtCore.QMetaObject.connectSlotsByName(message_dialog)
def retranslateUi(self, message_dialog):
_translate = QtCore.QCoreApplication.translate
message_dialog.setWindowTitle(_translate("message_dialog", "Message"))
self.message_label.setText(_translate("message_dialog", "Message!"))

43
ui/MessageDialog.ui

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>message_dialog</class>
<widget class="QDialog" name="message_dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>60</height>
</rect>
</property>
<property name="windowTitle">
<string>Message</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="message_label">
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="text">
<string>Message!</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

33
ui/RemoveVendorDialog.py

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'RemoveVendorDialog.ui'
#
# Created by: PyQt5 UI code generator 5.14.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_dialog_remove(object):
def setupUi(self, dialog_remove):
dialog_remove.setObjectName("dialog_remove")
dialog_remove.resize(399, 100)
self.label = QtWidgets.QLabel(dialog_remove)
self.label.setGeometry(QtCore.QRect(10, 10, 371, 41))
self.label.setObjectName("label")
self.buttonBox = QtWidgets.QDialogButtonBox(dialog_remove)
self.buttonBox.setGeometry(QtCore.QRect(210, 60, 164, 32))
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.retranslateUi(dialog_remove)
self.buttonBox.accepted.connect(dialog_remove.accept)
self.buttonBox.rejected.connect(dialog_remove.reject)
QtCore.QMetaObject.connectSlotsByName(dialog_remove)
def retranslateUi(self, dialog_remove):
_translate = QtCore.QCoreApplication.translate
dialog_remove.setWindowTitle(_translate("dialog_remove", "Remove Vendor"))
self.label.setText(_translate("dialog_remove", "Are you sure you want to remove this vendor?"))

45
ui/RemoveVendorDialog.ui

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>dialog_remove</class>
<widget class="QDialog" name="dialog_remove">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>100</height>
</rect>
</property>
<property name="windowTitle">
<string>Remove Vendor</string>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>371</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>Are you sure you want to remove this vendor?</string>
</property>
</widget>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>210</x>
<y>60</y>
<width>164</width>
<height>32</height>
</rect>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

192
ui/ReportResultWidget.py

@ -0,0 +1,192 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ReportResultWidget.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ReportResultWidget(object):
def setupUi(self, ReportResultWidget):
ReportResultWidget.setObjectName("ReportResultWidget")
ReportResultWidget.resize(600, 60)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(200)
sizePolicy.setHeightForWidth(ReportResultWidget.sizePolicy().hasHeightForWidth())
ReportResultWidget.setSizePolicy(sizePolicy)
ReportResultWidget.setMinimumSize(QtCore.QSize(600, 60))
ReportResultWidget.setMaximumSize(QtCore.QSize(16777215, 16777215))
ReportResultWidget.setSizeIncrement(QtCore.QSize(0, 1000))
font = QtGui.QFont()
font.setPointSize(9)
ReportResultWidget.setFont(font)
self.horizontalLayout = QtWidgets.QHBoxLayout(ReportResultWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.frame = QtWidgets.QFrame(ReportResultWidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
self.frame.setSizePolicy(sizePolicy)
self.frame.setMinimumSize(QtCore.QSize(600, 0))
self.frame.setFrameShape(QtWidgets.QFrame.Box)
self.frame.setFrameShadow(QtWidgets.QFrame.Sunken)
self.frame.setObjectName("frame")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.frame_6 = QtWidgets.QFrame(self.frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_6.sizePolicy().hasHeightForWidth())
self.frame_6.setSizePolicy(sizePolicy)
self.frame_6.setMinimumSize(QtCore.QSize(80, 50))
self.frame_6.setObjectName("frame_6")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.frame_6)
self.verticalLayout_5.setContentsMargins(-1, 0, -1, 0)
self.verticalLayout_5.setSpacing(3)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.report_type_label = QtWidgets.QLabel(self.frame_6)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.report_type_label.sizePolicy().hasHeightForWidth())
self.report_type_label.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.report_type_label.setFont(font)
self.report_type_label.setAlignment(QtCore.Qt.AlignCenter)
self.report_type_label.setObjectName("report_type_label")
self.verticalLayout_5.addWidget(self.report_type_label, 0, QtCore.Qt.AlignHCenter)
self.horizontalLayout_2.addWidget(self.frame_6)
self.frame_2 = QtWidgets.QFrame(self.frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth())
self.frame_2.setSizePolicy(sizePolicy)
self.frame_2.setObjectName("frame_2")
self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_2)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(6)
self.verticalLayout.setObjectName("verticalLayout")
self.file_frame = QtWidgets.QFrame(self.frame_2)
self.file_frame.setObjectName("file_frame")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.file_frame)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.file_label = QtWidgets.QLabel(self.file_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.file_label.sizePolicy().hasHeightForWidth())
self.file_label.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setUnderline(True)
self.file_label.setFont(font)
self.file_label.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.file_label.setStyleSheet("color: #0000EE")
self.file_label.setWordWrap(True)
self.file_label.setObjectName("file_label")
self.horizontalLayout_4.addWidget(self.file_label)
self.folder_button = QtWidgets.QPushButton(self.file_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.folder_button.sizePolicy().hasHeightForWidth())
self.folder_button.setSizePolicy(sizePolicy)
self.folder_button.setText("")
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/folder_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.folder_button.setIcon(icon)
self.folder_button.setObjectName("folder_button")
self.horizontalLayout_4.addWidget(self.folder_button)
self.verticalLayout.addWidget(self.file_frame)
self.message_label = QtWidgets.QLabel(self.frame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.message_label.sizePolicy().hasHeightForWidth())
self.message_label.setSizePolicy(sizePolicy)
self.message_label.setWordWrap(True)
self.message_label.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.message_label.setObjectName("message_label")
self.verticalLayout.addWidget(self.message_label)
self.horizontalLayout_2.addWidget(self.frame_2)
self.frame_4 = QtWidgets.QFrame(self.frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_4.sizePolicy().hasHeightForWidth())
self.frame_4.setSizePolicy(sizePolicy)
self.frame_4.setMinimumSize(QtCore.QSize(120, 50))
self.frame_4.setObjectName("frame_4")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.frame_4)
self.horizontalLayout_3.setContentsMargins(9, 0, -1, 0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.success_label = QtWidgets.QLabel(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.success_label.sizePolicy().hasHeightForWidth())
self.success_label.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.success_label.setFont(font)
self.success_label.setAlignment(QtCore.Qt.AlignCenter)
self.success_label.setObjectName("success_label")
self.horizontalLayout_3.addWidget(self.success_label)
self.retry_frame = QtWidgets.QFrame(self.frame_4)
self.retry_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.retry_frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.retry_frame.setObjectName("retry_frame")
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.retry_frame)
self.verticalLayout_7.setContentsMargins(-1, 0, -1, -1)
self.verticalLayout_7.setObjectName("verticalLayout_7")
self.label_6 = QtWidgets.QLabel(self.retry_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_6.sizePolicy().hasHeightForWidth())
self.label_6.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(False)
font.setWeight(50)
self.label_6.setFont(font)
self.label_6.setAlignment(QtCore.Qt.AlignCenter)
self.label_6.setObjectName("label_6")
self.verticalLayout_7.addWidget(self.label_6)
self.retry_check_box = QtWidgets.QCheckBox(self.retry_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.retry_check_box.sizePolicy().hasHeightForWidth())
self.retry_check_box.setSizePolicy(sizePolicy)
self.retry_check_box.setText("")
self.retry_check_box.setObjectName("retry_check_box")
self.verticalLayout_7.addWidget(self.retry_check_box, 0, QtCore.Qt.AlignHCenter)
self.horizontalLayout_3.addWidget(self.retry_frame)
self.horizontalLayout_2.addWidget(self.frame_4)
self.horizontalLayout.addWidget(self.frame)
self.retranslateUi(ReportResultWidget)
QtCore.QMetaObject.connectSlotsByName(ReportResultWidget)
def retranslateUi(self, ReportResultWidget):
_translate = QtCore.QCoreApplication.translate
ReportResultWidget.setWindowTitle(_translate("ReportResultWidget", "Report Result"))
self.report_type_label.setText(_translate("ReportResultWidget", "TR_J1"))
self.file_label.setText(_translate("ReportResultWidget", "Saved as: Bleh.tsv"))
self.message_label.setText(_translate("ReportResultWidget", "No exception messages"))
self.success_label.setText(_translate("ReportResultWidget", "Failed!"))
self.label_6.setText(_translate("ReportResultWidget", "Retry"))
import Resources_rc

356
ui/ReportResultWidget.ui

@ -0,0 +1,356 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ReportResultWidget</class>
<widget class="QWidget" name="ReportResultWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>60</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>200</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>60</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>1000</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Report Result</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>50</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>3</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="report_type_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>TR_J1</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="file_frame">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="file_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<underline>true</underline>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">color: #0000EE</string>
</property>
<property name="text">
<string>Saved as: Bleh.tsv</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="folder_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/folder_icon.png</normaloff>:/ui/resources/folder_icon.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="message_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>No exception messages</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>50</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="success_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Failed!</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="retry_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Retry</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QCheckBox" name="retry_check_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

44
ui/ReportTypeDialog.py

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ReportTypeDialog.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_report_type_dialog(object):
def setupUi(self, report_type_dialog):
report_type_dialog.setObjectName("report_type_dialog")
report_type_dialog.resize(433, 155)
self.verticalLayout = QtWidgets.QVBoxLayout(report_type_dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.report_type_combobox = QtWidgets.QComboBox(report_type_dialog)
self.report_type_combobox.setObjectName("report_type_combobox")
self.verticalLayout.addWidget(self.report_type_combobox)
self.buttonBox = QtWidgets.QDialogButtonBox(report_type_dialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(report_type_dialog)
self.buttonBox.accepted.connect(report_type_dialog.accept)
self.buttonBox.rejected.connect(report_type_dialog.reject)
QtCore.QMetaObject.connectSlotsByName(report_type_dialog)
def retranslateUi(self, report_type_dialog):
_translate = QtCore.QCoreApplication.translate
report_type_dialog.setWindowTitle(_translate("report_type_dialog", "Report Type"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
report_type_dialog = QtWidgets.QDialog()
ui = Ui_report_type_dialog()
ui.setupUi(report_type_dialog)
report_type_dialog.show()
sys.exit(app.exec_())

67
ui/ReportTypeDialog.ui

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>report_type_dialog</class>
<widget class="QDialog" name="report_type_dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>433</width>
<height>155</height>
</rect>
</property>
<property name="windowTitle">
<string>Report Type</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="report_type_combobox"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>report_type_dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>report_type_dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

71
ui/SearchAndClauseFrame.py

@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'SearchAndClauseFrame.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_search_and_clause_parameter_frame(object):
def setupUi(self, search_and_clause_parameter_frame):
search_and_clause_parameter_frame.setObjectName("search_and_clause_parameter_frame")
search_and_clause_parameter_frame.resize(542, 175)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(search_and_clause_parameter_frame.sizePolicy().hasHeightForWidth())
search_and_clause_parameter_frame.setSizePolicy(sizePolicy)
search_and_clause_parameter_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
search_and_clause_parameter_frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.gridLayout = QtWidgets.QGridLayout(search_and_clause_parameter_frame)
self.gridLayout.setObjectName("gridLayout")
self.search_or_clause_parameters_frame = QtWidgets.QFrame(search_and_clause_parameter_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_or_clause_parameters_frame.sizePolicy().hasHeightForWidth())
self.search_or_clause_parameters_frame.setSizePolicy(sizePolicy)
self.search_or_clause_parameters_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.search_or_clause_parameters_frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.search_or_clause_parameters_frame.setObjectName("search_or_clause_parameters_frame")
self.verticalLayout_22 = QtWidgets.QVBoxLayout(self.search_or_clause_parameters_frame)
self.verticalLayout_22.setObjectName("verticalLayout_22")
self.gridLayout.addWidget(self.search_or_clause_parameters_frame, 0, 0, 1, 1)
self.search_add_or_clause_button = QtWidgets.QPushButton(search_and_clause_parameter_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_add_or_clause_button.sizePolicy().hasHeightForWidth())
self.search_add_or_clause_button.setSizePolicy(sizePolicy)
self.search_add_or_clause_button.setObjectName("search_add_or_clause_button")
self.gridLayout.addWidget(self.search_add_or_clause_button, 1, 0, 1, 1)
self.search_remove_and_clause_button = QtWidgets.QPushButton(search_and_clause_parameter_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_remove_and_clause_button.sizePolicy().hasHeightForWidth())
self.search_remove_and_clause_button.setSizePolicy(sizePolicy)
self.search_remove_and_clause_button.setObjectName("search_remove_and_clause_button")
self.gridLayout.addWidget(self.search_remove_and_clause_button, 0, 1, 1, 1)
self.retranslateUi(search_and_clause_parameter_frame)
QtCore.QMetaObject.connectSlotsByName(search_and_clause_parameter_frame)
def retranslateUi(self, search_and_clause_parameter_frame):
_translate = QtCore.QCoreApplication.translate
search_and_clause_parameter_frame.setWindowTitle(_translate("search_and_clause_parameter_frame", "Frame"))
self.search_add_or_clause_button.setText(_translate("search_and_clause_parameter_frame", "Add \"Or\" Clause"))
self.search_remove_and_clause_button.setText(_translate("search_and_clause_parameter_frame", "Remove \"And\" Clause"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
search_and_clause_parameter_frame = QtWidgets.QFrame()
ui = Ui_search_and_clause_parameter_frame()
ui.setupUi(search_and_clause_parameter_frame)
search_and_clause_parameter_frame.show()
sys.exit(app.exec_())

76
ui/SearchAndClauseFrame.ui

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>search_and_clause_parameter_frame</class>
<widget class="QFrame" name="search_and_clause_parameter_frame">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>542</width>
<height>175</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Frame</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QFrame" name="search_or_clause_parameters_frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_22"/>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="search_add_or_clause_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add &quot;Or&quot; Clause</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="search_remove_and_clause_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove &quot;And&quot; Clause</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save