Compare commits

...

No commits in common. '9837a70f6605c97eac4e62687ff8d12ae28b50f3' and '6150f9cd92204a9b3209b7bba47afa8c99120801' have entirely different histories.

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

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')

0
DataStorage.py

2045
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)

204
ImportFile.py

@ -1,19 +1,30 @@
"""This module handles all operations involving importing reports."""
import shutil import shutil
import webbrowser import platform
from os import path, makedirs, system import ctypes
import csv
from os import path, makedirs
from PyQt5.QtCore import QModelIndex, QDate, Qt from PyQt5.QtCore import QModelIndex, QDate, Qt
from PyQt5.QtWidgets import QWidget, QDialog, QFileDialog from PyQt5.QtWidgets import QWidget, QDialog, QDialogButtonBox
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QIcon, QPixmap from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
from ui import MainWindow, MessageDialog, ReportResultWidget
import GeneralUtils
from Constants import *
from ui import ImportReportTab, ReportResultWidget
from ManageVendors import Vendor from ManageVendors import Vendor
from FetchData import REPORT_TYPES, CompletionStatus from FetchData import ALL_REPORTS, CompletionStatus
from Settings import SettingsModel from Settings import SettingsModel
import platform from ManageDB import UpdateDatabaseWorker
import shlex
class ProcessResult: 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): def __init__(self, vendor: Vendor, report_type: str):
self.vendor = vendor self.vendor = vendor
self.report_type = report_type self.report_type = report_type
@ -24,22 +35,30 @@ class ProcessResult:
self.file_path = "" self.file_path = ""
class ImportFileController: class ImportReportController:
def __init__(self, vendors: list, settings: SettingsModel, main_window_ui: MainWindow.Ui_mainWindow): """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 # region General
self.import_report_widget = import_report_widget
self.vendors = vendors self.vendors = vendors
self.date = QDate.currentDate() self.date = QDate.currentDate()
self.selected_vendor_index = -1 self.selected_vendor_index = -1
self.selected_report_type_index = -1 self.selected_report_type_index = -1
self.selected_file_name: str = ""
self.selected_file_path: str = "" self.selected_file_path: str = ""
self.settings = settings self.settings = settings
self.result_dialog = None self.result_dialog = None
# endregion # endregion
# region Vendors # region Vendors
self.vendor_list_view = main_window_ui.vendors_list_view_import self.vendor_list_view = import_report_ui.vendors_list_view_import
self.vendor_list_model = QStandardItemModel(self.vendor_list_view) self.vendor_list_model = QStandardItemModel(self.vendor_list_view)
self.vendor_list_view.setModel(self.vendor_list_model) self.vendor_list_view.setModel(self.vendor_list_model)
self.vendor_list_view.clicked.connect(self.on_vendor_selected) self.vendor_list_view.clicked.connect(self.on_vendor_selected)
@ -47,39 +66,48 @@ class ImportFileController:
# endregion # endregion
# region Report Types # region Report Types
self.report_type_list_view = main_window_ui.report_types_list_view_import 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_model = QStandardItemModel(self.report_type_list_view)
self.report_type_list_view.setModel(self.report_type_list_model) self.report_type_list_view.setModel(self.report_type_list_model)
self.report_type_list_view.clicked.connect(self.on_report_type_selected) self.report_type_list_view.clicked.connect(self.on_report_type_selected)
for report_type in REPORT_TYPES: for report_type in ALL_REPORTS:
item = QStandardItem(report_type) item = QStandardItem(report_type)
item.setEditable(False) item.setEditable(False)
self.report_type_list_model.appendRow(item) self.report_type_list_model.appendRow(item)
# endregion # endregion
# region Others # region Others
self.year_date_edit = main_window_ui.report_year_date_edit self.year_date_edit = import_report_ui.report_year_date_edit
self.year_date_edit.setDate(self.date) self.year_date_edit.setDate(self.date)
self.year_date_edit.dateChanged.connect(self.on_date_changed) self.year_date_edit.dateChanged.connect(self.on_date_changed)
self.select_file_btn = main_window_ui.select_file_button self.select_file_btn = import_report_ui.select_file_button
self.select_file_btn.clicked.connect(self.open_file_select_dialog) self.select_file_btn.clicked.connect(self.on_select_file_clicked)
self.selected_file_label = main_window_ui.selected_file_label self.selected_file_edit = import_report_ui.selected_file_edit
self.import_file_button = main_window_ui.import_file_button self.import_report_button = import_report_ui.import_report_button
self.import_file_button.clicked.connect(self.on_import_clicked) self.import_report_button.clicked.connect(self.on_import_clicked)
# endregion # endregion
def on_vendors_changed(self, vendors: list): 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.selected_vendor_index = -1
self.update_vendors(vendors) self.update_vendors(vendors)
self.update_vendors_ui() self.update_vendors_ui()
def update_vendors(self, vendors: list): 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 self.vendors = vendors
def update_vendors_ui(self): def update_vendors_ui(self):
"""Updates the UI to show vendors that support report import"""
self.vendor_list_model.clear() self.vendor_list_model.clear()
for vendor in self.vendors: for vendor in self.vendors:
item = QStandardItem(vendor.name) item = QStandardItem(vendor.name)
@ -87,50 +115,90 @@ class ImportFileController:
self.vendor_list_model.appendRow(item) self.vendor_list_model.appendRow(item)
def on_vendor_selected(self, model_index: QModelIndex): def on_vendor_selected(self, model_index: QModelIndex):
"""Handles the signal emitted when a vendor is selected"""
self.selected_vendor_index = model_index.row() self.selected_vendor_index = model_index.row()
def on_report_type_selected(self, model_index: QModelIndex): 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() self.selected_report_type_index = model_index.row()
def on_date_changed(self, date: QDate): def on_date_changed(self, date: QDate):
"""Handles the signal emitted when the target date is changed"""
self.date = date self.date = date
def open_file_select_dialog(self): def on_select_file_clicked(self):
dialog = QFileDialog() """Handles the signal emitted when the select file button is clicked"""
dialog.setFileMode(QFileDialog.ExistingFile) file_path = GeneralUtils.choose_file(TSV_FILTER + CSV_FILTER)
dialog.setNameFilter("All TSV files (*.tsv)") if file_path:
if dialog.exec_(): self.selected_file_path = file_path
self.selected_file_path = dialog.selectedFiles()[0] self.selected_file_edit.setText(file_path)
arr = self.selected_file_path.split("/")
self.selected_file_name = arr[max(len(arr), 1) - 1]
self.selected_file_label.setText(self.selected_file_name)
def on_import_clicked(self): def on_import_clicked(self):
"""Handles the signal emitted when the import button is clicked"""
if self.selected_vendor_index == -1: if self.selected_vendor_index == -1:
self.show_message("Select a vendor") GeneralUtils.show_message("Select a vendor")
return return
elif self.selected_report_type_index == -1: elif self.selected_report_type_index == -1:
self.show_message("Select a report type") GeneralUtils.show_message("Select a report type")
return return
elif self.selected_file_path == "": elif self.selected_file_path == "":
self.show_message("Select a file") GeneralUtils.show_message("Select a file")
return return
vendor = self.vendors[self.selected_vendor_index] vendor = self.vendors[self.selected_vendor_index]
report_type = REPORT_TYPES[self.selected_report_type_index] report_type = ALL_REPORTS[self.selected_report_type_index]
process_result = self.import_file(vendor, report_type) process_result = self.import_report(vendor, report_type)
self.show_result(process_result) self.show_result(process_result)
def import_file(self, vendor: Vendor, report_type: str) -> ProcessResult: 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) process_result = ProcessResult(vendor, report_type)
try: try:
dest_file_dir = f"{self.settings.yearly_directory}{self.date.toString('yyyy')}/{vendor.name}/"
dest_file_name = f"{self.date.toString('yyyy')}_{vendor.name}_{report_type}.tsv" 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}" dest_file_path = f"{dest_file_dir}{dest_file_name}"
self.verify_path_exists(dest_file_dir) # 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) self.copy_file(self.selected_file_path, dest_file_path)
process_result.file_dir = dest_file_dir process_result.file_dir = dest_file_dir
@ -138,21 +206,39 @@ class ImportFileController:
process_result.file_path = dest_file_path process_result.file_path = dest_file_path
process_result.completion_status = CompletionStatus.SUCCESSFUL 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: except Exception as e:
process_result.message = f"Exception: {e}" process_result.message = f"Exception: {e}"
process_result.completion_status = CompletionStatus.FAILED process_result.completion_status = CompletionStatus.FAILED
return process_result return process_result
def verify_path_exists(self, path_str: str):
if not path.isdir(path_str):
makedirs(path_str)
def copy_file(self, origin_path: str, dest_path: str): 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) shutil.copy2(origin_path, dest_path)
def show_result(self, process_result: ProcessResult): def show_result(self, process_result: ProcessResult):
self.result_dialog = QDialog(flags=Qt.WindowCloseButtonHint) """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") self.result_dialog.setWindowTitle("Import Result")
vertical_layout = QtWidgets.QVBoxLayout(self.result_dialog) vertical_layout = QtWidgets.QVBoxLayout(self.result_dialog)
vertical_layout.setContentsMargins(5, 5, 5, 5) vertical_layout.setContentsMargins(5, 5, 5, 5)
@ -161,6 +247,10 @@ class ImportFileController:
report_result_ui = ReportResultWidget.Ui_ReportResultWidget() report_result_ui = ReportResultWidget.Ui_ReportResultWidget()
report_result_ui.setupUi(report_result_widget) 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 vendor = process_result.vendor
report_type = process_result.report_type report_type = process_result.report_type
@ -172,11 +262,11 @@ class ImportFileController:
report_result_ui.retry_frame.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.setText(f"Saved as: {process_result.file_name}")
report_result_ui.file_label.mousePressEvent = lambda event: self.open_explorer(process_result.file_path) report_result_ui.file_label.mousePressEvent = \
lambda event: GeneralUtils.open_file_or_dir(process_result.file_path)
folder_pixmap = QPixmap("./ui/resources/folder_icon.png") report_result_ui.folder_button.clicked.connect(
report_result_ui.folder_button.setIcon(QIcon(folder_pixmap)) lambda: GeneralUtils.open_file_or_dir(process_result.file_dir))
report_result_ui.folder_button.clicked.connect(lambda: self.open_explorer(process_result.file_dir))
report_result_ui.success_label.setText("Successful!") report_result_ui.success_label.setText("Successful!")
report_result_ui.retry_frame.hide() report_result_ui.retry_frame.hide()
@ -188,25 +278,7 @@ class ImportFileController:
report_result_ui.message_label.setText(process_result.message) report_result_ui.message_label.setText(process_result.message)
vertical_layout.addWidget(report_result_widget) vertical_layout.addWidget(report_result_widget)
vertical_layout.addWidget(button_box)
self.result_dialog.show() self.result_dialog.show()
def show_message(self, message: str):
message_dialog = QDialog(flags=Qt.WindowCloseButtonHint)
message_dialog_ui = MessageDialog.Ui_message_dialog()
message_dialog_ui.setupUi(message_dialog)
message_label = message_dialog_ui.message_label
message_label.setText(message)
message_dialog.show()
def open_explorer(self, file_path: str):
if path.exists(file_path):
if(platform.system()=="Windows"):
webbrowser.open(path.realpath(file_path))
elif(platform.system()=="Darwin"):
system("open " + shlex.quote(file_path))
else:
self.show_message(f"\'{file_path}\' does not exist")

0
JsonUtils.py

118
MainDriver.py

@ -1,13 +1,19 @@
import sys import sys
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QFrame, QHBoxLayout, QPushButton
import ui.MainWindow from PyQt5.QtGui import QIcon, QPixmap
from ui import MainWindow, ManageVendorsTab, SettingsTab, FetchReportsTab, FetchSpecialReportsTab, ImportReportTab,\
SearchTab, VisualTab, CostsTab
from ManageVendors import ManageVendorsController from ManageVendors import ManageVendorsController
from FetchData import FetchReportsController, FetchSpecialReportsController from FetchData import FetchReportsController, FetchSpecialReportsController
from ImportFile import ImportFileController from ImportFile import ImportReportController
from Costs import CostsController
from Search import SearchController from Search import SearchController
from Settings import SettingsController from Settings import SettingsController, SettingsModel
from Visual import VisualController
import GeneralUtils
import ManageDB
from Constants import *
# region debug_stuff # region debug_stuff
@ -29,27 +35,109 @@ if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)
app.setStyleSheet("QWidget {font-family: Segoe UI; font-size: 12pt;}")
main_window = QMainWindow() main_window = QMainWindow()
main_window_ui = ui.MainWindow.Ui_mainWindow() main_window_ui = MainWindow.Ui_mainWindow()
main_window_ui.setupUi(main_window) main_window_ui.setupUi(main_window)
GeneralUtils.main_window = main_window
# region Setup Tab Controllers # region Setup Tab Controllers
manage_vendors_controller = ManageVendorsController(main_window_ui) settings_tab = QWidget(main_window)
settings_controller = SettingsController(main_window_ui) 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_controller = FetchReportsController(manage_vendors_controller.vendors, settings_controller.settings,
main_window_ui) 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, fetch_special_reports_controller = FetchSpecialReportsController(manage_vendors_controller.vendors,
settings_controller.settings, main_window_ui) settings_controller.settings,
search_controller = SearchController(main_window_ui) fetch_special_reports_tab,
import_file_controller = ImportFileController(manage_vendors_controller.vendors, settings_controller.settings, fetch_special_reports_ui)
main_window_ui)
# endregion 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 # region Connect Signals
manage_vendors_controller.vendors_changed_signal.connect(fetch_reports_controller.on_vendors_changed) 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(fetch_special_reports_controller.on_vendors_changed)
manage_vendors_controller.vendors_changed_signal.connect(import_file_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 # endregion
main_window.show() main_window.show()

1364
ManageDB.py

File diff suppressed because it is too large Load Diff

428
ManageVendors.py

@ -1,103 +1,125 @@
"""This module handles all operations involving managing vendors."""
import csv import csv
import os
import json import json
import validators import validators
from PyQt5.QtWidgets import QDialog, QLabel, QDialogButtonBox, QFileDialog from PyQt5.QtWidgets import QDialog, QLabel, QDialogButtonBox, QWidget
from PyQt5.QtGui import QStandardItemModel, QStandardItem from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtCore import Qt, QObject, QModelIndex, pyqtSignal from PyQt5.QtCore import Qt, QObject, QModelIndex, pyqtSignal
from ui import MainWindow, AddVendorDialog, MessageDialog, RemoveVendorDialog from ui import ManageVendorsTab, AddVendorDialog, RemoveVendorDialog
import DataStorage import ManageDB
import webbrowser import GeneralUtils
from JsonUtils import JsonModel from GeneralUtils import JsonModel
from Constants import *
VENDORS_FILE_DIR = "./all_data/vendor_manager/" from Settings import SettingsModel
VENDORS_FILE_NAME = "vendors.dat"
VENDORS_FILE_PATH = VENDORS_FILE_DIR + VENDORS_FILE_NAME
EXPORT_VENDORS_FILE_NAME = "exported_vendor_data.tsv"
help_site = "https://github.com/CS-4820-Library-Project/Libly/wiki"
class Vendor(JsonModel): class Vendor(JsonModel):
def __init__(self, name: str, customer_id: str, base_url: str, requestor_id: str, api_key: str, platform: str, """This holds a vendor's information
is_local: bool, description: str, companies: str):
: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.name = name
self.customer_id = customer_id
self.base_url = base_url self.base_url = base_url
self.customer_id = customer_id
self.requestor_id = requestor_id self.requestor_id = requestor_id
self.api_key = api_key self.api_key = api_key
self.platform = platform self.platform = platform
self.is_local = is_local self.is_non_sushi = is_non_sushi
self.description = description self.description = description
self.companies = companies self.companies = companies
@classmethod @classmethod
def from_json(cls, json_dict: dict): 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 "" name = json_dict["name"] if "name" in json_dict else ""
customer_id = json_dict["customer_id"] if "customer_id" 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 "" 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 "" 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 "" api_key = json_dict["api_key"] if "api_key" in json_dict else ""
platform = json_dict["platform"] if "platform" in json_dict else "" platform = json_dict["platform"] if "platform" in json_dict else ""
is_local = json_dict["is_local"] if "is_local" in json_dict else False 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 "" description = json_dict["description"] if "description" in json_dict else ""
companies = json_dict["companies"] if "companies" in json_dict else "" companies = json_dict["companies"] if "companies" in json_dict else ""
return cls(name, customer_id, base_url, requestor_id, api_key, platform, is_local, description, companies) return cls(name, base_url, customer_id, requestor_id, api_key, platform, is_non_sushi, description, companies)
class ManageVendorsController(QObject): 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) vendors_changed_signal = pyqtSignal(list)
def __init__(self, main_window_ui: MainWindow.Ui_mainWindow): def __init__(self, manage_vendors_widget: QWidget, manage_vendors_ui: ManageVendorsTab.Ui_manage_vendors_tab,
settings: SettingsModel):
super().__init__() super().__init__()
self.manage_vendors_widget = manage_vendors_widget
self.selected_index = -1 self.selected_index = -1
self.edit_vendor_details_frame = main_window_ui.edit_vendor_details_frame self.edit_vendor_details_frame = manage_vendors_ui.edit_vendor_details_frame
self.edit_vendor_options_frame = main_window_ui.edit_vendor_options_frame self.edit_vendor_options_frame = manage_vendors_ui.edit_vendor_options_frame
self.name_line_edit = main_window_ui.nameEdit self.name_line_edit = manage_vendors_ui.nameEdit
self.customer_id_line_edit = main_window_ui.customerIdEdit self.customer_id_line_edit = manage_vendors_ui.customerIdEdit
self.base_url_line_edit = main_window_ui.baseUrlEdit self.base_url_line_edit = manage_vendors_ui.baseUrlEdit
self.requestor_id_line_edit = main_window_ui.requestorIdEdit self.requestor_id_line_edit = manage_vendors_ui.requestorIdEdit
self.api_key_line_edit = main_window_ui.apiKeyEdit self.api_key_line_edit = manage_vendors_ui.apiKeyEdit
self.platform_line_edit = main_window_ui.platformEdit self.platform_line_edit = manage_vendors_ui.platformEdit
self.local_only_check_box = main_window_ui.local_only_check_box self.non_Sushi_check_box = manage_vendors_ui.non_Sushi_check_box
self.description_text_edit = main_window_ui.descriptionEdit self.description_text_edit = manage_vendors_ui.descriptionEdit
self.companies_text_edit = main_window_ui.companiesEdit self.companies_text_edit = manage_vendors_ui.companiesEdit
self.name_validation_label = main_window_ui.name_validation_label 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.name_validation_label.hide()
self.url_validation_label = main_window_ui.url_validation_label self.url_validation_label = manage_vendors_ui.url_validation_label
self.url_validation_label.hide() self.url_validation_label.hide()
self.help_button = main_window_ui.helpButton self.save_vendor_changes_button = manage_vendors_ui.saveVendorChangesButton
self.save_vendor_changes_button = main_window_ui.saveVendorChangesButton self.undo_vendor_changes_button = manage_vendors_ui.undoVendorChangesButton
self.undo_vendor_changes_button = main_window_ui.undoVendorChangesButton self.remove_vendor_button = manage_vendors_ui.removeVendorButton
self.remove_vendor_button = main_window_ui.removeVendorButton self.add_vendor_button = manage_vendors_ui.addVendorButton
self.add_vendor_button = main_window_ui.addVendorButton self.export_vendors_button = manage_vendors_ui.exportVendorsButton
self.export_vendors_button = main_window_ui.exportVendorsButton self.import_vendors_button = manage_vendors_ui.importVendorsButton
# TODO(Ziheng): add export_vendors_button
self.import_vendors_button = main_window_ui.importVendorsButton
# TODO(Ziheng): add import_vendors_button
self.help_button.clicked.connect(self.help_method)
self.save_vendor_changes_button.clicked.connect(self.modify_vendor) self.save_vendor_changes_button.clicked.connect(self.modify_vendor)
self.undo_vendor_changes_button.clicked.connect(self.populate_edit_vendor_view) self.undo_vendor_changes_button.clicked.connect(self.populate_edit_vendor_view)
self.remove_vendor_button.clicked.connect(self.open_remove_vendor_dialog) self.remove_vendor_button.clicked.connect(self.on_remove_vendor_clicked)
self.add_vendor_button.clicked.connect(self.open_add_vendor_dialog) self.add_vendor_button.clicked.connect(self.on_add_vendor_clicked)
self.export_vendors_button.clicked.connect(self.open_custom_folder_select_dialog) self.export_vendors_button.clicked.connect(self.on_export_vendors_clicked)
# TODO(Ziheng): add connection to dialog for export_vendors_button to export dir path self.import_vendors_button.clicked.connect(self.on_import_vendors_clicked)
self.import_vendors_button.clicked.connect(self.open_file_select_dialog)
# TODO(Ziheng): add connection to dialog for import_vendors_button to import file self.vendor_list_view = manage_vendors_ui.vendorsListView
self.vendor_list_view = main_window_ui.vendorsListView
self.vendor_list_model = QStandardItemModel(self.vendor_list_view) self.vendor_list_model = QStandardItemModel(self.vendor_list_view)
self.vendor_list_view.setModel(self.vendor_list_model) self.vendor_list_view.setModel(self.vendor_list_model)
self.vendor_list_view.clicked.connect(self.on_vendor_selected) self.vendor_list_view.clicked.connect(self.on_vendor_selected)
self.settings = settings
self.vendors = [] self.vendors = []
self.vendor_names = set() # Hash set for faster operations self.vendor_names = set() # Hash set for faster operations
vendors_json_string = DataStorage.read_json_file(VENDORS_FILE_PATH) vendors_json_string = GeneralUtils.read_json_file(VENDORS_FILE_PATH)
vendor_dicts = json.loads(vendors_json_string) vendor_dicts = json.loads(vendors_json_string)
for json_dict in vendor_dicts: for json_dict in vendor_dicts:
vendor = Vendor.from_json(json_dict) vendor = Vendor.from_json(json_dict)
@ -107,10 +129,21 @@ class ManageVendorsController(QObject):
self.update_vendors_ui() self.update_vendors_ui()
def on_vendor_selected(self, model_index: QModelIndex): 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.selected_index = model_index.row()
self.populate_edit_vendor_view() self.populate_edit_vendor_view()
def on_name_text_changed(self, new_name: str, original_name: str, validation_label: QLabel, validate: bool = True): 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: if not validate:
validation_label.hide() validation_label.hide()
return return
@ -123,6 +156,12 @@ class ManageVendorsController(QObject):
validation_label.setText(message) validation_label.setText(message)
def on_url_text_changed(self, url: str, validation_label: QLabel, validate: bool = True): 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: if not validate:
validation_label.hide() validation_label.hide()
return return
@ -135,6 +174,12 @@ class ManageVendorsController(QObject):
validation_label.setText(message) validation_label.setText(message)
def validate_new_name(self, new_name: str, original_name: str = "") -> (bool, str): 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: if not new_name:
return False, "Vendor name can't be empty" return False, "Vendor name can't be empty"
elif new_name.lower() in self.vendor_names: elif new_name.lower() in self.vendor_names:
@ -146,6 +191,11 @@ class ManageVendorsController(QObject):
return True, "" return True, ""
def validate_url(self, url: str) -> (bool, str): 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): if not validators.url(url):
return False, "Invalid Url" return False, "Invalid Url"
elif not url.endswith("/reports"): elif not url.endswith("/reports"):
@ -154,6 +204,7 @@ class ManageVendorsController(QObject):
return True, "" return True, ""
def update_vendors_ui(self): def update_vendors_ui(self):
"""Updates the UI to show all vendors"""
self.vendor_list_model.clear() self.vendor_list_model.clear()
for vendor in self.vendors: for vendor in self.vendors:
item = QStandardItem(vendor.name) item = QStandardItem(vendor.name)
@ -163,17 +214,23 @@ class ManageVendorsController(QObject):
self.populate_edit_vendor_view() self.populate_edit_vendor_view()
def update_vendor_names(self): def update_vendor_names(self):
"""Updates the local set of vendor names used for validation"""
self.vendor_names.clear() self.vendor_names.clear()
for vendor in self.vendors: for vendor in self.vendors:
self.vendor_names.add(vendor.name.lower()) self.vendor_names.add(vendor.name.lower())
def add_vendor(self, new_vendor: Vendor) -> (bool, str): 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 # Check if vendor is valid
is_valid, message = self.validate_new_name(new_vendor.name) is_valid, message = self.validate_new_name(new_vendor.name)
if not is_valid: if not is_valid:
return is_valid, message return is_valid, message
if not new_vendor.is_local: if not new_vendor.is_non_sushi:
is_valid, message = self.validate_url(new_vendor.base_url) is_valid, message = self.validate_url(new_vendor.base_url)
if not is_valid: if not is_valid:
return is_valid, message return is_valid, message
@ -184,8 +241,9 @@ class ManageVendorsController(QObject):
return True, "" return True, ""
def modify_vendor(self): def modify_vendor(self):
"""Updates a vendor's information in the system if the vendor is valid"""
if self.selected_index < 0: if self.selected_index < 0:
print("No vendor selected") if self.settings.show_debug_messages: print("No vendor selected")
return return
selected_vendor = self.vendors[self.selected_index] selected_vendor = self.vendors[self.selected_index]
@ -195,24 +253,30 @@ class ManageVendorsController(QObject):
original_name = selected_vendor.name original_name = selected_vendor.name
is_valid, message = self.validate_new_name(new_name, original_name) is_valid, message = self.validate_new_name(new_name, original_name)
if not is_valid: if not is_valid:
self.show_message(message) GeneralUtils.show_message(message)
return return
if not self.local_only_check_box.isChecked(): if not self.non_Sushi_check_box.isChecked():
url = self.base_url_line_edit.text() url = self.base_url_line_edit.text()
is_valid, message = self.validate_url(url) is_valid, message = self.validate_url(url)
if not is_valid: if not is_valid:
self.show_message(message) GeneralUtils.show_message(message)
return return
# Apply Changes # 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.name = self.name_line_edit.text()
selected_vendor.base_url = self.base_url_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.customer_id = self.customer_id_line_edit.text()
selected_vendor.requestor_id = self.requestor_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.api_key = self.api_key_line_edit.text()
selected_vendor.platform = self.platform_line_edit.text() selected_vendor.platform = self.platform_line_edit.text()
selected_vendor.is_local = self.local_only_check_box.checkState() == Qt.Checked selected_vendor.is_non_sushi = self.non_Sushi_check_box.checkState() == Qt.Checked
selected_vendor.description = self.description_text_edit.toPlainText() selected_vendor.description = self.description_text_edit.toPlainText()
selected_vendor.companies = self.companies_text_edit.toPlainText() selected_vendor.companies = self.companies_text_edit.toPlainText()
@ -220,9 +284,133 @@ class ManageVendorsController(QObject):
self.update_vendor_names() self.update_vendor_names()
self.vendors_changed_signal.emit(self.vendors) self.vendors_changed_signal.emit(self.vendors)
self.save_all_vendors_to_disk() self.save_all_vendors_to_disk()
self.show_message("Changes Saved!")
def open_add_vendor_dialog(self): 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 = QDialog()
vendor_dialog_ui = AddVendorDialog.Ui_addVendorDialog() vendor_dialog_ui = AddVendorDialog.Ui_addVendorDialog()
vendor_dialog_ui.setupUi(vendor_dialog) vendor_dialog_ui.setupUi(vendor_dialog)
@ -233,10 +421,14 @@ class ManageVendorsController(QObject):
requestor_id_edit = vendor_dialog_ui.requestorIdEdit requestor_id_edit = vendor_dialog_ui.requestorIdEdit
api_key_edit = vendor_dialog_ui.apiKeyEdit api_key_edit = vendor_dialog_ui.apiKeyEdit
platform_edit = vendor_dialog_ui.platformEdit platform_edit = vendor_dialog_ui.platformEdit
local_only_check_box = vendor_dialog_ui.local_only_check_box non_sushi_check_box = vendor_dialog_ui.non_Sushi_check_box
description_edit = vendor_dialog_ui.descriptionEdit description_edit = vendor_dialog_ui.descriptionEdit
companies_edit = vendor_dialog_ui.companiesEdit 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 = vendor_dialog_ui.name_validation_label
name_validation_label.hide() name_validation_label.hide()
url_validation_label = vendor_dialog_ui.url_validation_label url_validation_label = vendor_dialog_ui.url_validation_label
@ -248,15 +440,9 @@ class ManageVendorsController(QObject):
lambda url: self.on_url_text_changed(url, url_validation_label)) lambda url: self.on_url_text_changed(url, url_validation_label))
def attempt_add_vendor(): def attempt_add_vendor():
vendor = Vendor(name_edit.text(), vendor = Vendor(name_edit.text(), base_url_edit.text(), customer_id_edit.text(), requestor_id_edit.text(),
customer_id_edit.text(), api_key_edit.text(), platform_edit.text(), non_sushi_check_box.checkState() == Qt.Checked,
base_url_edit.text(), description_edit.toPlainText(), companies_edit.toPlainText())
requestor_id_edit.text(),
api_key_edit.text(),
platform_edit.text(),
local_only_check_box.checkState() == Qt.Checked,
description_edit.toPlainText(),
companies_edit.toPlainText())
is_valid, message = self.add_vendor(vendor) is_valid, message = self.add_vendor(vendor)
if is_valid: if is_valid:
@ -268,7 +454,7 @@ class ManageVendorsController(QObject):
self.save_all_vendors_to_disk() self.save_all_vendors_to_disk()
vendor_dialog.close() vendor_dialog.close()
else: else:
self.show_message(message) GeneralUtils.show_message(message)
button_box = vendor_dialog_ui.buttonBox button_box = vendor_dialog_ui.buttonBox
ok_button = button_box.button(QDialogButtonBox.Ok) ok_button = button_box.button(QDialogButtonBox.Ok)
@ -278,23 +464,28 @@ class ManageVendorsController(QObject):
vendor_dialog.exec_() vendor_dialog.exec_()
def open_file_select_dialog(self): def on_import_vendors_clicked(self):
dialog = QFileDialog() """Handles the signal emitted when the import vendors button is clicked.
dialog.setFileMode(QFileDialog.ExistingFile)
if dialog.exec_(): A file select dialog is shown to allow the user to select the vendors TSV file to import. The selected file is
selected_file_path = dialog.selectedFiles()[0] then imported.
self.import_vendors_tsv(selected_file_path) """
self.show_message(f"Import successful!") file_path = GeneralUtils.choose_file(TSV_FILTER)
if file_path:
def open_custom_folder_select_dialog(self): self.import_vendors_tsv(file_path)
dialog = QFileDialog()
dialog.setFileMode(QFileDialog.Directory) def on_export_vendors_clicked(self):
if dialog.exec_(): """Handles the signal emitted when the export vendors button is clicked.
directory = dialog.selectedFiles()[0] + "/"
self.export_vendors_tsv(directory) A folder select dialog is shown to allow the user to select the target directory to export the vendors file to.
self.show_message(f"Exported as {EXPORT_VENDORS_FILE_NAME}") 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): def populate_edit_vendor_view(self):
"""Populates the edit vendor view with the selected vendors's information"""
if self.selected_index >= 0: if self.selected_index >= 0:
selected_vendor = self.vendors[self.selected_index] selected_vendor = self.vendors[self.selected_index]
@ -310,7 +501,7 @@ class ManageVendorsController(QObject):
self.requestor_id_line_edit.setText(selected_vendor.requestor_id) self.requestor_id_line_edit.setText(selected_vendor.requestor_id)
self.api_key_line_edit.setText(selected_vendor.api_key) self.api_key_line_edit.setText(selected_vendor.api_key)
self.platform_line_edit.setText(selected_vendor.platform) self.platform_line_edit.setText(selected_vendor.platform)
self.local_only_check_box.setChecked(selected_vendor.is_local) self.non_Sushi_check_box.setChecked(selected_vendor.is_non_sushi)
self.description_text_edit.setPlainText(selected_vendor.description) self.description_text_edit.setPlainText(selected_vendor.description)
self.companies_text_edit.setPlainText(selected_vendor.companies) self.companies_text_edit.setPlainText(selected_vendor.companies)
@ -331,13 +522,17 @@ class ManageVendorsController(QObject):
self.requestor_id_line_edit.setText("") self.requestor_id_line_edit.setText("")
self.api_key_line_edit.setText("") self.api_key_line_edit.setText("")
self.platform_line_edit.setText("") self.platform_line_edit.setText("")
self.local_only_check_box.setChecked(False) self.non_Sushi_check_box.setChecked(False)
self.description_text_edit.setPlainText("") self.description_text_edit.setPlainText("")
self.companies_text_edit.setPlainText("") self.companies_text_edit.setPlainText("")
self.set_edit_vendor_view_state(False) self.set_edit_vendor_view_state(False)
def set_edit_vendor_view_state(self, is_enabled): 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: if is_enabled:
self.edit_vendor_details_frame.setEnabled(True) self.edit_vendor_details_frame.setEnabled(True)
self.edit_vendor_options_frame.setEnabled(True) self.edit_vendor_options_frame.setEnabled(True)
@ -345,7 +540,12 @@ class ManageVendorsController(QObject):
self.edit_vendor_details_frame.setEnabled(False) self.edit_vendor_details_frame.setEnabled(False)
self.edit_vendor_options_frame.setEnabled(False) self.edit_vendor_options_frame.setEnabled(False)
def open_remove_vendor_dialog(self): 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 = QDialog()
dialog_remove_ui = RemoveVendorDialog.Ui_dialog_remove() dialog_remove_ui = RemoveVendorDialog.Ui_dialog_remove()
dialog_remove_ui.setupUi(dialog_remove) dialog_remove_ui.setupUi(dialog_remove)
@ -366,44 +566,40 @@ class ManageVendorsController(QObject):
dialog_remove.exec_() dialog_remove.exec_()
def save_all_vendors_to_disk(self): 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) json_string = json.dumps(self.vendors, default=lambda o: o.__dict__, indent=4)
DataStorage.save_json_file(VENDORS_FILE_DIR, VENDORS_FILE_NAME, json_string) GeneralUtils.save_json_file(VENDORS_FILE_DIR, VENDORS_FILE_NAME, json_string)
def show_message(self, message: str):
message_dialog = QDialog(flags=Qt.WindowCloseButtonHint)
message_dialog_ui = MessageDialog.Ui_message_dialog()
message_dialog_ui.setupUi(message_dialog)
message_label = message_dialog_ui.message_label
message_label.setText(message)
message_dialog.exec_()
def sort_vendors(self): def sort_vendors(self):
"""Sorts the vendors alphabetically based their names"""
self.vendors = sorted(self.vendors, key=lambda vendor: vendor.name.lower()) self.vendors = sorted(self.vendors, key=lambda vendor: vendor.name.lower())
def import_vendors_tsv(self, file_path): 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: try:
tsv_file = open(file_path, 'r', encoding="utf-8", newline='') tsv_file = open(file_path, 'r', encoding="utf-8", newline='')
reader = csv.DictReader(tsv_file, delimiter='\t') reader = csv.DictReader(tsv_file, delimiter='\t')
for row in reader: for row in reader:
if 'is_local' in row: if 'is_non_sushi' in row:
is_local = row['is_local'].lower() == "true" is_non_sushi = row['is_non_sushi'].lower() == "true"
else: else:
is_local = False is_non_sushi = False
vendor = Vendor(row['name'] if 'name' in row else "", vendor = Vendor(row['name'] if 'name' in row else "",
row['customer_id'] if 'customer_id' in row else "",
row['base_url'] if 'base_url' 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['requestor_id'] if 'requestor_id' in row else "",
row['api_key'] if 'api_key' in row else "", row['api_key'] if 'api_key' in row else "",
row['platform'] if 'platform' in row else "", row['platform'] if 'platform' in row else "",
is_local, is_non_sushi,
row['description'] if 'description' in row else "", row['description'] if 'description' in row else "",
row['companies'] if 'companies' in row else "") row['companies'] if 'companies' in row else "")
is_valid, message = self.add_vendor(vendor) is_valid, message = self.add_vendor(vendor)
if not is_valid: if not is_valid:
print(message) if self.settings.show_debug_messages: print(message)
tsv_file.close() tsv_file.close()
@ -414,18 +610,25 @@ class ManageVendorsController(QObject):
self.populate_edit_vendor_view() self.populate_edit_vendor_view()
self.vendors_changed_signal.emit(self.vendors) self.vendors_changed_signal.emit(self.vendors)
self.save_all_vendors_to_disk() self.save_all_vendors_to_disk()
GeneralUtils.show_message(f"Import successful!")
except Exception as e: except Exception as e:
print(f"File import failed: {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): 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}" file_path = f"{dir_path}{EXPORT_VENDORS_FILE_NAME}"
column_names = ["name", column_names = ["name",
"customer_id",
"base_url", "base_url",
"customer_id",
"requestor_id", "requestor_id",
"api_key", "api_key",
"platform", "platform",
"is_local", "is_non_sushi",
"description", "description",
"companies"] "companies"]
try: try:
@ -437,10 +640,9 @@ class ManageVendorsController(QObject):
tsv_dict_writer.writerow(vendor.__dict__) tsv_dict_writer.writerow(vendor.__dict__)
tsv_file.close() tsv_file.close()
GeneralUtils.show_message(f"Exported to {file_path}")
except Exception as e: except Exception as e:
print(f"File export failed: {e}") if self.settings.show_debug_messages: print(f"File export failed: {e}")
GeneralUtils.show_message(f"File export failed: {e}")
def help_method(self):
webbrowser.open(help_site, 2, True)

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'),
])

32
README.md

@ -1,11 +1,27 @@
# Libly # COUNTER 5 Report Tool
This project is written is Python 3.7. Anaconda is used to manage the packages and environment used in this project, everything is up to date. 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 required packages are PyQt5 and requests. The project is written with Python 3.7. The PyQt GUI framework is used to create a user friendly (hopefully) GUI.
The project's UI is developed using PyQt ## 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
# Setup Instructions (Windows) ## 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] - 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/] ### Add Python to environment variables [https://datatofish.com/add-python-to-windows-path/]
- Open control panel - Open control panel
@ -38,16 +54,16 @@ type pip -v into command prompt, this should return the version of PIP that is i
# Developer Setup (using Anaconda and Pycharm) ## Developer Setup (using Anaconda and Pycharm)
- Download and install Anaconda: https://www.anaconda.com/distribution/#download-section - Download and install Anaconda: https://www.anaconda.com/distribution/#download-section
- Download and install PyCharm: https://www.jetbrains.com/pycharm/download/ - Download and install PyCharm: https://www.jetbrains.com/pycharm/download/
## Using Anaconda ### Using Anaconda
- Launch Anaconda Navigator (Anaconda GUI) - Launch Anaconda Navigator (Anaconda GUI)
- Go to Environments on the left pane - Go to Environments on the left pane
- Search for and ensure that pyqt and requests packages are installed - Search for and ensure that pyqt and requests packages are installed
## Using PyCharm ### Using PyCharm
- Download and open the project using PyCharm - Download and open the project using PyCharm
- Go to File->Settings - Go to File->Settings
- On the left pane, select Project->Project Interpreter - On the left pane, select Project->Project Interpreter

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

295
Search.py

@ -1,119 +1,182 @@
import csv
import os import os
import shlex
import sip import sip
import json import json
from PyQt5.QtCore import QDate from typing import Tuple, Dict
from PyQt5.QtWidgets import QFrame, QVBoxLayout, QComboBox, QLineEdit, QFileDialog from PyQt5.QtGui import QIntValidator, QDoubleValidator
from PyQt5.QtWidgets import QFrame, QVBoxLayout, QComboBox, QLineEdit, QSpacerItem, QSizePolicy, QLabel
import ManageDB import ManageDB
import DataStorage from Settings import SettingsModel
from ui import MainWindow, SearchAndClauseFrame, SearchOrClauseFrame from ui import SearchTab, SearchAndFrame, SearchOrFrame
from Constants import *
from GeneralUtils import *
class SearchController: class SearchController:
def __init__(self, main_window_ui: MainWindow.Ui_mainWindow): """Controls the Search tab
self.main_window = main_window_ui
: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 # set up report types combobox
self.report_parameter = main_window_ui.search_report_parameter_combobox self.report_parameter = search_ui.search_report_parameter_combobox
self.report_parameter.addItems(ManageDB.DATABASE_REPORTS) self.report_parameter.addItems(ALL_REPORTS)
self.report_parameter.addItems(ManageDB.ITEM_REPORTS)
self.report_parameter.addItems(ManageDB.PLATFORM_REPORTS)
self.report_parameter.addItems(ManageDB.TITLE_REPORTS)
# set up start year dateedit # set up start year dateedit
self.start_year_parameter = main_window_ui.search_start_year_parameter_dateedit self.start_year_parameter = search_ui.search_start_year_parameter_dateedit
self.start_year_parameter.setDate(QDate.currentDate()) self.start_year_parameter.setDate(QDate.currentDate())
# set up end year dateedit # set up end year dateedit
self.end_year_parameter = main_window_ui.search_end_year_parameter_dateedit self.end_year_parameter = search_ui.search_end_year_parameter_dateedit
self.end_year_parameter.setDate(QDate.currentDate()) self.end_year_parameter.setDate(QDate.currentDate())
# set up search button # set up search button
self.search_button = main_window_ui.search_button self.search_button = search_ui.search_button
self.search_button.clicked.connect(self.search) self.search_button.clicked.connect(self.search)
self.open_results_checkbox = main_window_ui.search_open_results_checkbox 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 # set up export button
self.export_button = main_window_ui.search_export_button self.export_button = search_ui.search_export_button
self.export_button.clicked.connect(self.export_parameters) self.export_button.clicked.connect(self.export_parameters)
# set up import button # set up import button
self.import_button = main_window_ui.search_import_button self.import_button = search_ui.search_import_button
self.import_button.clicked.connect(self.import_parameters) self.import_button.clicked.connect(self.import_parameters)
# set up restore database button
self.restore_database_button = main_window_ui.search_restore_database_button
self.restore_database_button.clicked.connect(self.restore_database)
# set up add and clause button # set up add and clause button
def add_and_and_or_clause(): 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() and_clause = self.add_and_clause()
self.add_or_clause(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 = main_window_ui.search_add_and_button self.add_and_button = search_ui.search_add_and_button
self.add_and_button.clicked.connect(add_and_and_or_clause) self.add_and_button.clicked.connect(add_and_and_or_clause)
# resets the search clauses when the report type is changed # resets the search clauses when the report type is changed
def refresh_and_add_clauses(): def refresh_and_add_clauses():
"""Resets the search clauses, then adds an and clause containing an or clause"""
self.refresh_clauses() self.refresh_clauses()
add_and_and_or_clause() add_and_and_or_clause()
self.report_parameter.currentTextChanged.connect(refresh_and_add_clauses) self.report_parameter.currentTextChanged.connect(refresh_and_add_clauses)
self.and_clause_parameters = None self.and_clause_parameters_scrollarea = search_ui.search_and_clause_parameters_scrollarea
self.and_clause_parameters_frame = None
refresh_and_add_clauses() refresh_and_add_clauses()
def refresh_clauses(self): # resets the search clauses def update_settings(self, settings: SettingsModel):
self.and_clause_parameters = QFrame() """Called when the settings are saved
self.and_clause_parameters.setLayout(QVBoxLayout())
self.main_window.search_and_clause_parameters_scrollarea.setWidget(self.and_clause_parameters) :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): def add_and_clause(self) -> SearchAndFrame.Ui_search_and_clause_parameter_frame:
"""Adds an and clause to the search"""
and_clause = QFrame() and_clause = QFrame()
and_clause_ui = SearchAndClauseFrame.Ui_search_and_clause_parameter_frame() and_clause_ui = SearchAndFrame.Ui_search_and_clause_parameter_frame()
and_clause_ui.setupUi(and_clause) and_clause_ui.setupUi(and_clause)
# set up add or clause button # set up add or clause button
def add_or_to_this_and(): def add_or_to_this_and():
"""Adds an or clause to this and clause"""
self.add_or_clause(and_clause_ui) 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) and_clause_ui.search_add_or_clause_button.clicked.connect(add_or_to_this_and)
# set up remove current and clause button # set up remove current and clause button
def remove_this_and(): def remove_this_and():
self.and_clause_parameters.layout().removeWidget(and_clause) """Removes this and clause"""
self.and_clause_parameters_frame.layout().removeWidget(and_clause)
sip.delete(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) and_clause_ui.search_remove_and_clause_button.clicked.connect(remove_this_and)
# add to the layout # add to the layout
self.and_clause_parameters.layout().addWidget(and_clause) self.and_clause_parameters_frame.layout().insertWidget(self.and_clause_parameters_frame.layout().count() - 1,
and_clause)
return and_clause_ui return and_clause_ui
def add_or_clause(self, and_clause): 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 = QFrame()
or_clause_ui = SearchOrClauseFrame.Ui_search_or_clause_parameter_frame() or_clause_ui = SearchOrFrame.Ui_search_or_clause_parameter_frame()
or_clause_ui.setupUi(or_clause) or_clause_ui.setupUi(or_clause)
# fill field combobox # fill field combobox
field_combobox = or_clause_ui.search_field_parameter_combobox field_combobox = or_clause_ui.search_field_parameter_combobox
for field in ManageDB.get_report_fields_list(self.report_parameter.currentText(), True): for field in ManageDB.get_view_report_fields_list(self.report_parameter.currentText()):
if 'calculation' not in field.keys() and field['name'] not in ManageDB.FIELDS_NOT_IN_SEARCH: if field[NAME_KEY] not in FIELDS_NOT_IN_SEARCH_DROPDOWN:
field_combobox.addItem(field['name']) 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)
# TODO make value check for type field_combobox.currentTextChanged.connect(on_field_changed)
on_field_changed()
# fill comparison operator combobox # fill comparison operator combobox
comparison_combobox = or_clause_ui.search_comparison_parameter_combobox comparison_combobox = or_clause_ui.search_comparison_parameter_combobox
comparison_combobox.addItems(('=', '<=', '<', '>=', '>', 'LIKE')) 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 # set up remove current or clause button
def remove_this_or(): def remove_this_or():
"""Removes this or clause"""
and_clause.search_or_clause_parameters_frame.layout().removeWidget(or_clause) and_clause.search_or_clause_parameters_frame.layout().removeWidget(or_clause)
sip.delete(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) or_clause_ui.search_remove_or_clause_button.clicked.connect(remove_this_or)
@ -122,88 +185,86 @@ class SearchController:
return or_clause_ui return or_clause_ui
def export_parameters(self): # export current search parameters to selected file def hide_or_label_in_first_or_clause(self, and_clause: SearchAndFrame.Ui_search_and_clause_parameter_frame):
parameters = self.get_search_parameters() """Hides the or label for the first or clause in an and clause
print(parameters)
dialog = QFileDialog() :param and_clause: the and clause"""
dialog.setFileMode(QFileDialog.AnyFile) or_clause = and_clause.search_or_clause_parameters_frame.findChild(QFrame, 'search_or_clause_parameter_frame')
dialog.setAcceptMode(QFileDialog.AcceptSave) if or_clause:
dialog.setNameFilter('JSON files (*.dat)') or_clause.findChild(QLabel, "search_or_label").hide()
if dialog.exec_():
file_name = dialog.selectedFiles()[0] def export_parameters(self):
if file_name[-4:].lower() != '.dat' and file_name != '': """Exports the current search parameters to the selected file"""
file_name += '.tsv' file_name = choose_save(JSON_FILTER)
file = open(file_name, 'w', encoding='utf-8') 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': if file.mode == 'w':
json.dump(parameters, file) json.dump({'report': report, 'start_year': start_year, 'end_year': end_year,
'search_parameters': search_parameters}, file)
def import_parameters(self): # import search parameters from selected file show_message('Search saved to ' + file_name)
dialog = QFileDialog() else:
dialog.setFileMode(QFileDialog.ExistingFile) print('Error, no file location selected')
dialog.setNameFilter('JSON files (*.dat)')
if dialog.exec_(): def import_parameters(self):
fields = json.loads(DataStorage.read_json_file(dialog.selectedFiles()[0])) """Imports a new set of search parameters from the selected file"""
print(fields) file_name = choose_file(JSON_FILTER)
if file_name != '':
fields = json.loads(read_json_file(file_name))
self.report_parameter.setCurrentText(fields['report']) self.report_parameter.setCurrentText(fields['report'])
self.start_year_parameter.setDate(QDate(fields['start_year'], 1, 1)) self.start_year_parameter.setDate(QDate(fields['start_year'], 1, 1))
self.end_year_parameter.setDate(QDate(fields['end_year'], 1, 1)) self.end_year_parameter.setDate(QDate(fields['end_year'], 1, 1))
clauses = fields['search_parameters'] clauses = fields['search_parameters']
print(clauses)
self.refresh_clauses() self.refresh_clauses()
for clause in clauses: for clause in clauses:
and_clause = self.add_and_clause() and_clause = self.add_and_clause()
for sub_clause in clause: for sub_clause in clause:
or_clause = self.add_or_clause(and_clause) or_clause = self.add_or_clause(and_clause)
or_clause.search_field_parameter_combobox.setCurrentText(sub_clause['field']) or_clause.search_field_parameter_combobox.setCurrentText(sub_clause[FIELD_KEY])
or_clause.search_comparison_parameter_combobox.setCurrentText(sub_clause['comparison']) or_clause.search_comparison_parameter_combobox.setCurrentText(sub_clause[COMPARISON_KEY])
or_clause.search_value_parameter_lineedit.setText(sub_clause['value']) or_clause.search_value_parameter_lineedit.setText(str(sub_clause[VALUE_KEY]))
def search(self): # submit search result to database and open results def search(self):
parameters = self.get_search_parameters() """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 query to get search results
sql_text = ManageDB.search_sql_text(parameters['report'], parameters['start_year'], sql_text, data = ManageDB.search_sql_text(report, start_year, end_year, search_parameters)
parameters['end_year'], parameters['search_parameters'])
print(sql_text) # testing
headers = [] headers = []
for field in ManageDB.get_report_fields_list(parameters['report'], True): for field in ManageDB.get_view_report_fields_list(report):
headers.append(field['name']) headers.append(field[NAME_KEY])
dialog = QFileDialog() file_name = choose_save(TSV_FILTER)
dialog.setFileMode(QFileDialog.AnyFile) if file_name != '':
dialog.setAcceptMode(QFileDialog.AcceptSave) if not file_name.lower().endswith('.tsv'):
dialog.setNameFilter('TSV files (*.tsv)')
if dialog.exec_():
file_name = dialog.selectedFiles()[0]
if file_name[-4:].lower() != '.tsv' and file_name != '':
file_name += '.tsv' file_name += '.tsv'
connection = ManageDB.create_connection(ManageDB.DATABASE_LOCATION) connection = ManageDB.create_connection(DATABASE_LOCATION)
if connection is not None: if connection is not None:
results = ManageDB.run_select_sql(connection, sql_text) results = ManageDB.run_select_sql(connection, sql_text, data)
results.insert(0, headers)
print(results)
file = open(file_name, 'w', newline="", encoding='utf-8')
if file.mode == 'w':
output = csv.writer(file, delimiter='\t', quotechar='\"')
for row in results:
output.writerow(row)
open_file_switcher = {'nt': (lambda: os.startfile(file_name)),
# TODO check file_name for special characters and quote
'posix': (lambda: os.system("open " + shlex.quote(file_name)))}
if self.open_results_checkbox.isChecked():
open_file_switcher[os.name]()
else:
print('Error: could not open file ' + file_name)
connection.close() 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: else:
print('Error, no connection') print('Error, no connection')
else: else:
print('Error, no file location selected') print('Error, no file location selected')
def get_search_parameters(self): 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 # get report type
report = self.report_parameter.currentText() report = self.report_parameter.currentText()
# get start year # get start year
@ -212,31 +273,29 @@ class SearchController:
end_year = int(self.end_year_parameter.text()) end_year = int(self.end_year_parameter.text())
search_parameters = [] search_parameters = []
for and_widget in self.and_clause_parameters.findChildren(QFrame, 'search_and_clause_parameter_frame'): for and_widget in self.and_clause_parameters_frame.findChildren(QFrame, 'search_and_clause_parameter_frame'):
# iterate over and clauses # iterate over and clauses
print('and: ' + str(and_widget.objectName()) + ' ' + str(and_widget)) # testing
or_clause_parameters = and_widget.findChild(QFrame, 'search_or_clause_parameters_frame') or_clause_parameters = and_widget.findChild(QFrame, 'search_or_clause_parameters_frame')
or_clauses = [] or_clauses = []
for or_widget in or_clause_parameters.findChildren(QFrame, 'search_or_clause_parameter_frame'): for or_widget in or_clause_parameters.findChildren(QFrame, 'search_or_clause_parameter_frame'):
# iterate over child or clauses # iterate over child or clauses
print('\tor: ' + str(or_widget.objectName()) + ' ' + str(or_widget)) # testing
# get parameters for clause # get parameters for clause
field_parameter = or_widget.findChild(QComboBox, 'search_field_parameter_combobox').currentText() field_parameter_combobox = or_widget.findChild(QComboBox, 'search_field_parameter_combobox')
comparison_parameter = or_widget.findChild(QComboBox, field_parameter = field_parameter_combobox.currentText()
'search_comparison_parameter_combobox').currentText() comparison_parameter_combobox = or_widget.findChild(QComboBox, 'search_comparison_parameter_combobox')
value_parameter = or_widget.findChild(QLineEdit, 'search_value_parameter_lineedit').text() comparison_parameter = comparison_parameter_combobox.currentText()
# TODO check for special characters 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( or_clauses.append(
{'field': field_parameter, 'comparison': comparison_parameter, 'value': value_parameter}) {FIELD_KEY: field_parameter, COMPARISON_KEY: comparison_parameter, VALUE_KEY: value_parameter})
search_parameters.append(or_clauses) search_parameters.append(or_clauses)
return {'report': report, 'start_year': start_year, 'end_year': end_year, return report, start_year, end_year, search_parameters
'search_parameters': search_parameters}
def restore_database(self):
ManageDB.setup_database(True)
reports = ManageDB.get_all_reports()
for report in reports:
print(os.path.basename(report['file']))
ManageDB.insert_single_file(report['file'], report['vendor'], report['year'])
print('done')

263
Settings.py

@ -1,48 +1,56 @@
from enum import Enum """This module handles all operations involving the user's settings."""
from PyQt5.QtCore import Qt, QObject, pyqtSignal
from PyQt5.QtWidgets import QDialog, QFileDialog
from ui import MainWindow, MessageDialog
from JsonUtils import JsonModel
import json
import DataStorage
SETTINGS_FILE_DIR = "./all_data/settings/" import json
SETTINGS_FILE_NAME = "settings.dat" 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): class Setting(Enum):
"""An enum of all settings"""
YEARLY_DIR = 0 YEARLY_DIR = 0
OTHER_DIR = 1 OTHER_DIR = 1
REQUEST_INTERVAL = 2 REQUEST_INTERVAL = 2
REQUEST_TIMEOUT = 3 REQUEST_TIMEOUT = 3
CONCURRENT_VENDORS = 4 CONCURRENT_VENDORS = 4
CONCURRENT_REPORTS = 5 CONCURRENT_REPORTS = 5
EMPTY_CELL = 6 USER_AGENT = 6
# Default Settings
YEARLY_DIR = "./all_data/yearly_files/"
OTHER_DIR = "./all_data/other_files/"
REQUEST_INTERVAL = 3 # Seconds
REQUEST_TIMEOUT = 120 # Seconds
CONCURRENT_VENDORS = 5
CONCURRENT_REPORTS = 5
EMPTY_CELL = ""
class SettingsModel(JsonModel): class SettingsModel(JsonModel):
def __init__(self, yearly_directory: str, other_directory: str, request_interval: int, request_timeout: int, """This holds the user's settings.
concurrent_vendors: int, concurrent_reports: int, empty_cell: str):
self.yearly_directory = yearly_directory :param yearly_directory: The directory where yearly reports are saved. Yearly reports are reports that include all
self.other_directory = other_directory 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_interval = request_interval
self.request_timeout = request_timeout self.request_timeout = request_timeout
self.concurrent_vendors = concurrent_vendors self.concurrent_vendors = concurrent_vendors
self.concurrent_reports = concurrent_reports self.concurrent_reports = concurrent_reports
self.empty_cell = empty_cell self.user_agent = user_agent
self.default_currency = default_currency
@classmethod @classmethod
def from_json(cls, json_dict: dict): 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"]\ yearly_directory = json_dict["yearly_directory"]\
if "yearly_directory" in json_dict else YEARLY_DIR if "yearly_directory" in json_dict else YEARLY_DIR
other_directory = json_dict["other_directory"]\ other_directory = json_dict["other_directory"]\
@ -55,112 +63,151 @@ class SettingsModel(JsonModel):
if "concurrent_vendors" in json_dict else CONCURRENT_VENDORS if "concurrent_vendors" in json_dict else CONCURRENT_VENDORS
concurrent_reports = int(json_dict["concurrent_reports"])\ concurrent_reports = int(json_dict["concurrent_reports"])\
if "concurrent_reports" in json_dict else CONCURRENT_REPORTS if "concurrent_reports" in json_dict else CONCURRENT_REPORTS
empty_cell = json_dict["empty_cell"]\ user_agent = json_dict["user_agent"]\
if "empty_cell" in json_dict else EMPTY_CELL 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(yearly_directory, other_directory, request_interval, request_timeout, concurrent_vendors, return cls(show_debug_messages, yearly_directory, other_directory, request_interval, request_timeout,
concurrent_reports, empty_cell) concurrent_vendors, concurrent_reports, user_agent, default_currency)
def show_message(message: str): class SettingsController(QObject):
message_dialog = QDialog(flags=Qt.WindowCloseButtonHint) """Controls the Settings tab
message_dialog_ui = MessageDialog.Ui_message_dialog()
message_dialog_ui.setupUi(message_dialog)
message_label = message_dialog_ui.message_label :param settings_widget: The settings widget.
message_label.setText(message) :param settings_ui: The UI for settings_widget.
"""
settings_changed_signal = pyqtSignal(SettingsModel)
message_dialog.exec_() def __init__(self, settings_widget: QWidget, settings_ui: SettingsTab.Ui_settings_tab):
class SettingsController:
def __init__(self, main_window_ui: MainWindow.Ui_mainWindow):
# region General # region General
json_string = DataStorage.read_json_file(SETTINGS_FILE_DIR + SETTINGS_FILE_NAME) 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) json_dict = json.loads(json_string)
self.settings = SettingsModel.from_json(json_dict) 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 # endregion
# region Reports # region Reports
self.yearly_dir_edit = main_window_ui.yearly_directory_edit self.yearly_dir_edit = settings_ui.yearly_directory_edit
self.other_dir_edit = main_window_ui.other_directory_edit self.other_dir_edit = settings_ui.other_directory_edit
self.request_interval_spin_box = settings_ui.request_interval_spin_box
main_window_ui.yearly_directory_button.clicked.connect( self.request_timeout_spin_box = settings_ui.request_timeout_spin_box
lambda: self.open_file_select_dialog(Setting.YEARLY_DIR)) self.concurrent_vendors_spin_box = settings_ui.concurrent_vendors_spin_box
main_window_ui.other_directory_button.clicked.connect( self.concurrent_reports_spin_box = settings_ui.concurrent_reports_spin_box
lambda: self.open_file_select_dialog(Setting.OTHER_DIR)) self.user_agent_edit = settings_ui.user_agent_edit
self.yearly_dir_edit.setText(self.settings.yearly_directory) self.yearly_dir_edit.setText(self.settings.yearly_directory)
self.other_dir_edit.setText(self.settings.other_directory) self.other_dir_edit.setText(self.settings.other_directory)
main_window_ui.request_interval_spin_box.setValue(self.settings.request_interval) self.request_interval_spin_box.setValue(self.settings.request_interval)
main_window_ui.request_timeout_spin_box.setValue(self.settings.request_timeout) self.request_timeout_spin_box.setValue(self.settings.request_timeout)
main_window_ui.concurrent_vendors_spin_box.setValue(self.settings.concurrent_vendors) self.concurrent_vendors_spin_box.setValue(self.settings.concurrent_vendors)
main_window_ui.concurrent_reports_spin_box.setValue(self.settings.concurrent_reports) self.concurrent_reports_spin_box.setValue(self.settings.concurrent_reports)
main_window_ui.empty_cell_edit.setText(self.settings.empty_cell) self.user_agent_edit.setText(self.settings.user_agent)
self.yearly_dir_edit.textEdited.connect( settings_ui.yearly_directory_button.clicked.connect(
lambda text: self.on_setting_changed(Setting.YEARLY_DIR, text)) lambda: self.on_directory_setting_clicked(Setting.YEARLY_DIR))
self.other_dir_edit.textEdited.connect( settings_ui.other_directory_button.clicked.connect(
lambda text: self.on_setting_changed(Setting.OTHER_DIR, text)) lambda: self.on_directory_setting_clicked(Setting.OTHER_DIR))
main_window_ui.request_interval_spin_box.valueChanged.connect(
lambda value: self.on_setting_changed(Setting.REQUEST_INTERVAL, value)) # Reports Help Messages
main_window_ui.request_timeout_spin_box.valueChanged.connect( settings_ui.yearly_directory_help_button.clicked.connect(
lambda value: self.on_setting_changed(Setting.REQUEST_TIMEOUT, value)) lambda: GeneralUtils.show_message("This is where the calendar-year reports will be saved"))
main_window_ui.concurrent_vendors_spin_box.valueChanged.connect( settings_ui.other_directory_help_button.clicked.connect(
lambda value: self.on_setting_changed(Setting.CONCURRENT_VENDORS, value)) lambda: GeneralUtils.show_message("This is where the special and non-calendar-year date range reports will "
main_window_ui.concurrent_reports_spin_box.valueChanged.connect( "be saved by default"))
lambda value: self.on_setting_changed(Setting.CONCURRENT_REPORTS, value)) settings_ui.request_interval_help_button.clicked.connect(
main_window_ui.empty_cell_edit.textEdited.connect( lambda: GeneralUtils.show_message("The number of seconds the program will wait between sending each report "
lambda text: self.on_setting_changed(Setting.EMPTY_CELL, text)) "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 # endregion
# region Reports Help Messages # region Costs
main_window_ui.yearly_directory_help_button.clicked.connect( self.default_currency_combobox = settings_ui.settings_costs_default_currency_combobox
lambda: show_message("This is where yearly files will be saved by default")) self.default_currency_combobox.addItems(CURRENCY_LIST)
main_window_ui.other_directory_help_button.clicked.connect( self.default_currency_combobox.setCurrentText(self.settings.default_currency)
lambda: show_message("This is where special and non-yearly files will be saved by default"))
main_window_ui.request_interval_help_button.clicked.connect(
lambda: show_message("The amount of time to wait between a vendor's report requests"))
main_window_ui.request_timeout_help_button.clicked.connect(
lambda: show_message("The amount of time to wait before cancelling a request"))
main_window_ui.concurrent_vendors_help_button.clicked.connect(
lambda: show_message("The maximum number of vendors to work on at the same time"))
main_window_ui.concurrent_reports_help_button.clicked.connect(
lambda: show_message("The maximum number of reports to work on at the same time, per vendor"))
main_window_ui.empty_cell_help_button.clicked.connect(
lambda: show_message("Empty cells will be replaced by whatever is in here"))
# endregion # endregion
def on_setting_changed(self, setting: Setting, setting_value): # region Search
if setting == Setting.YEARLY_DIR: # set up restore database button
self.settings.yearly_directory = setting_value self.is_rebuilding_database = False
elif setting == Setting.OTHER_DIR: self.update_database_dialog = ManageDB.UpdateDatabaseProgressDialogController(self.settings_widget)
self.settings.other_directory = setting_value self.rebuild_database_button = settings_ui.settings_rebuild_database_button
elif setting == Setting.REQUEST_INTERVAL: self.rebuild_database_button.clicked.connect(self.on_rebuild_database_clicked)
self.settings.request_interval = int(setting_value) # endregion
elif setting == Setting.REQUEST_TIMEOUT:
self.settings.request_timeout = int(setting_value)
elif setting == Setting.CONCURRENT_VENDORS:
self.settings.concurrent_vendors = int(setting_value)
elif setting == Setting.CONCURRENT_REPORTS:
self.settings.concurrent_reports = int(setting_value)
elif setting == Setting.EMPTY_CELL:
self.settings.empty_cell = setting_value
self.save_settings_to_disk() settings_ui.save_button.clicked.connect(self.on_save_button_clicked)
def open_file_select_dialog(self, setting: Setting): def on_directory_setting_clicked(self, setting: Setting):
dialog = QFileDialog() """Handles the signal emitted when a choose folder button is clicked
dialog.setFileMode(QFileDialog.Directory)
if dialog.exec_(): :param setting: The setting to be changed
directory = dialog.selectedFiles()[0] + "/" """
dir_path = GeneralUtils.choose_directory()
if dir_path:
if setting == Setting.YEARLY_DIR: if setting == Setting.YEARLY_DIR:
self.yearly_dir_edit.setText(directory) self.yearly_dir_edit.setText(dir_path)
elif setting == Setting.OTHER_DIR: elif setting == Setting.OTHER_DIR:
self.other_dir_edit.setText(directory) self.other_dir_edit.setText(dir_path)
self.on_setting_changed(setting, directory) 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): def save_settings_to_disk(self):
"""Saves all settings to disk"""
json_string = json.dumps(self.settings, default=lambda o: o.__dict__) json_string = json.dumps(self.settings, default=lambda o: o.__dict__)
DataStorage.save_json_file(SETTINGS_FILE_DIR, SETTINGS_FILE_NAME, json_string) 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

0
dev_notes.md

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

14
requirements.txt

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

BIN
tests/.DS_Store vendored

Binary file not shown.

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()

2
tests/test_FetchProgressDialog.py

@ -10,7 +10,7 @@ fetch_progress_dialog_ui = FetchProgressDialog.Ui_FetchProgressDialog()
fetch_progress_dialog_ui.setupUi(fetch_progress_dialog) fetch_progress_dialog_ui.setupUi(fetch_progress_dialog)
class MyTestCase(unittest.TestCase): class FetchProgressDialogTests(unittest.TestCase):
def test_defaults(self): def test_defaults(self):
'''Test the defaults''' '''Test the defaults'''
self.assertEqual(fetch_progress_dialog_ui.status_label.text(), "Fetching...") self.assertEqual(fetch_progress_dialog_ui.status_label.text(), "Fetching...")

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()

25
tests/test_ImportFile.py

@ -5,11 +5,11 @@ from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import QDate from PyQt5.QtCore import QDate
from PyQt5.QtGui import QStandardItemModel from PyQt5.QtGui import QStandardItemModel
from ui import MainWindow from ui import MainWindow
from ImportFile import ImportFileController from ImportFile import ImportReportController
from ManageVendors import Vendor from ManageVendors import Vendor
from FetchData import REPORT_TYPES, CompletionStatus from FetchData import ALL_REPORTS, CompletionStatus
import Settings import Settings
import DataStorage import GeneralUtils
import json import json
@ -24,7 +24,7 @@ def vendors() -> list:
"test vendor.dat should be placed in ./tests/data/vendor_manager/" "test vendor.dat should be placed in ./tests/data/vendor_manager/"
vendor_list = [] vendor_list = []
vendors_json_string = DataStorage.read_json_file("./data/vendor_manager/vendors.dat") vendors_json_string = GeneralUtils.read_json_file("./data/vendor_manager/vendors.dat")
vendor_dicts = json.loads(vendors_json_string) vendor_dicts = json.loads(vendors_json_string)
for json_dict in vendor_dicts: for json_dict in vendor_dicts:
vendor = Vendor.from_json(json_dict) vendor = Vendor.from_json(json_dict)
@ -41,7 +41,8 @@ def settings() -> Settings.SettingsModel:
Settings.REQUEST_TIMEOUT, Settings.REQUEST_TIMEOUT,
Settings.CONCURRENT_VENDORS, Settings.CONCURRENT_VENDORS,
Settings.CONCURRENT_REPORTS, Settings.CONCURRENT_REPORTS,
Settings.EMPTY_CELL) Settings.EMPTY_CELL,
Settings.USER_AGENT)
@pytest.fixture @pytest.fixture
@ -50,7 +51,7 @@ def controller(qtbot, settings): # ImportFileController without populated vendo
window_ui = MainWindow.Ui_mainWindow() window_ui = MainWindow.Ui_mainWindow()
window_ui.setupUi(window) window_ui.setupUi(window)
c = ImportFileController([], settings, window_ui) c = ImportReportController([], settings, window_ui)
yield c yield c
@ -60,7 +61,7 @@ def controller_v(qtbot, vendors, settings): # ImportFileController with populat
window_ui = MainWindow.Ui_mainWindow() window_ui = MainWindow.Ui_mainWindow()
window_ui.setupUi(window) window_ui.setupUi(window)
c = ImportFileController(vendors, settings, window_ui) c = ImportReportController(vendors, settings, window_ui)
yield c yield c
@ -126,7 +127,7 @@ def test_on_import_clicked(controller_v):
controller_v.selected_report_type_index = 1 controller_v.selected_report_type_index = 1
vendor = controller_v.vendors[controller_v.selected_vendor_index] vendor = controller_v.vendors[controller_v.selected_vendor_index]
report_type = REPORT_TYPES[controller_v.selected_report_type_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_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_name = f"{controller_v.date.toString('yyyy')}_{vendor.name}_{report_type}.tsv"
file_path = file_dir + file_name file_path = file_dir + file_name
@ -149,21 +150,21 @@ def test_import_file(controller_v):
controller_v.selected_report_type_index = 1 controller_v.selected_report_type_index = 1
vendor = controller_v.vendors[controller_v.selected_vendor_index] vendor = controller_v.vendors[controller_v.selected_vendor_index]
report_type = REPORT_TYPES[controller_v.selected_report_type_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_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_name = f"{controller_v.date.toString('yyyy')}_{vendor.name}_{report_type}.tsv"
file_path = file_dir + file_name file_path = file_dir + file_name
# No file selected # No file selected
assert controller_v.import_file(vendor, report_type).completion_status == CompletionStatus.FAILED assert controller_v.import_report(vendor, report_type).completion_status == CompletionStatus.FAILED
# Invalid file selected # Invalid file selected
controller_v.selected_file_path = "./data/invalid_file" controller_v.selected_file_path = "./data/invalid_file"
assert controller_v.import_file(vendor, report_type).completion_status == CompletionStatus.FAILED assert controller_v.import_report(vendor, report_type).completion_status == CompletionStatus.FAILED
# Valid file selected # Valid file selected
controller_v.selected_file_path = "./data/test_file_for_import.tsv" controller_v.selected_file_path = "./data/test_file_for_import.tsv"
assert controller_v.import_file(vendor, report_type).completion_status == CompletionStatus.SUCCESSFUL assert controller_v.import_report(vendor, report_type).completion_status == CompletionStatus.SUCCESSFUL
assert path.isfile(file_path) assert path.isfile(file_path)

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()

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()

BIN
ui/.DS_Store vendored

Binary file not shown.

138
ui/AddVendorDialog.py

@ -2,16 +2,18 @@
# Form implementation generated from reading ui file 'AddVendorDialog.ui' # Form implementation generated from reading ui file 'AddVendorDialog.ui'
# #
# Created by: PyQt5 UI code generator 5.9.2 # Created by: PyQt5 UI code generator 5.12.3
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_addVendorDialog(object): class Ui_addVendorDialog(object):
def setupUi(self, addVendorDialog): def setupUi(self, addVendorDialog):
addVendorDialog.setObjectName("addVendorDialog") addVendorDialog.setObjectName("addVendorDialog")
addVendorDialog.resize(600, 548) addVendorDialog.resize(600, 620)
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(11) font.setPointSize(11)
addVendorDialog.setFont(font) addVendorDialog.setFont(font)
@ -27,84 +29,118 @@ class Ui_addVendorDialog(object):
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame) self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
self.gridLayout_2.setSpacing(20) self.gridLayout_2.setSpacing(20)
self.gridLayout_2.setObjectName("gridLayout_2") self.gridLayout_2.setObjectName("gridLayout_2")
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 = QtWidgets.QLabel(self.frame)
self.label.setObjectName("label")
self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
self.baseUrlEdit = QtWidgets.QLineEdit(self.frame)
self.baseUrlEdit.setObjectName("baseUrlEdit")
self.gridLayout_2.addWidget(self.baseUrlEdit, 2, 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_2 = QtWidgets.QLabel(self.frame)
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 4, 0, 1, 1)
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_7 = QtWidgets.QLabel(self.frame) self.label_7 = QtWidgets.QLabel(self.frame)
self.label_7.setObjectName("label_7") self.label_7.setObjectName("label_7")
self.gridLayout_2.addWidget(self.label_7, 9, 0, 1, 1, QtCore.Qt.AlignTop) 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 = QtWidgets.QPlainTextEdit(self.frame)
self.companiesEdit.setObjectName("companiesEdit") self.companiesEdit.setObjectName("companiesEdit")
self.gridLayout_2.addWidget(self.companiesEdit, 10, 1, 1, 1) 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 = QtWidgets.QLabel(self.frame)
self.label_6.setObjectName("label_6") self.label_6.setObjectName("label_6")
self.gridLayout_2.addWidget(self.label_6, 7, 0, 1, 1) self.gridLayout_2.addWidget(self.label_6, 7, 0, 1, 1)
self.label_9 = QtWidgets.QLabel(self.frame) self.frame_2 = QtWidgets.QFrame(self.frame)
self.label_9.setObjectName("label_9") self.frame_2.setObjectName("frame_2")
self.gridLayout_2.addWidget(self.label_9, 10, 0, 1, 1, QtCore.Qt.AlignTop) 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 = QtWidgets.QLineEdit(self.frame)
self.customerIdEdit.setObjectName("customerIdEdit") self.customerIdEdit.setObjectName("customerIdEdit")
self.gridLayout_2.addWidget(self.customerIdEdit, 4, 1, 1, 1) 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 = QtWidgets.QLineEdit(self.frame)
self.apiKeyEdit.setObjectName("apiKeyEdit") self.apiKeyEdit.setObjectName("apiKeyEdit")
self.gridLayout_2.addWidget(self.apiKeyEdit, 6, 1, 1, 1) self.gridLayout_2.addWidget(self.apiKeyEdit, 6, 1, 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.platformEdit = QtWidgets.QLineEdit(self.frame)
self.platformEdit.setObjectName("platformEdit")
self.gridLayout_2.addWidget(self.platformEdit, 7, 1, 1, 1)
self.descriptionEdit = QtWidgets.QPlainTextEdit(self.frame) self.descriptionEdit = QtWidgets.QPlainTextEdit(self.frame)
self.descriptionEdit.setObjectName("descriptionEdit") self.descriptionEdit.setObjectName("descriptionEdit")
self.gridLayout_2.addWidget(self.descriptionEdit, 9, 1, 1, 1) self.gridLayout_2.addWidget(self.descriptionEdit, 9, 1, 1, 1)
self.requestorIdEdit = QtWidgets.QLineEdit(self.frame) self.label = QtWidgets.QLabel(self.frame)
self.requestorIdEdit.setObjectName("requestorIdEdit") self.label.setObjectName("label")
self.gridLayout_2.addWidget(self.requestorIdEdit, 5, 1, 1, 1) 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 = QtWidgets.QLabel(self.frame)
self.label_4.setObjectName("label_4") self.label_4.setObjectName("label_4")
self.gridLayout_2.addWidget(self.label_4, 5, 0, 1, 1) self.gridLayout_2.addWidget(self.label_4, 5, 0, 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.local_only_check_box = QtWidgets.QCheckBox(self.frame)
self.local_only_check_box.setText("")
self.local_only_check_box.setObjectName("local_only_check_box")
self.gridLayout_2.addWidget(self.local_only_check_box, 8, 1, 1, 1)
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.gridLayout.addWidget(self.frame, 0, 0, 1, 1) self.gridLayout.addWidget(self.frame, 0, 0, 1, 1)
self.retranslateUi(addVendorDialog) self.retranslateUi(addVendorDialog)
QtCore.QMetaObject.connectSlotsByName(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): def retranslateUi(self, addVendorDialog):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
addVendorDialog.setWindowTitle(_translate("addVendorDialog", "Add Vendor")) 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.name_validation_label.setText(_translate("addVendorDialog", "Validation label"))
self.label.setText(_translate("addVendorDialog", "Name")) 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_2.setText(_translate("addVendorDialog", "Customer ID"))
self.label_3.setText(_translate("addVendorDialog", "Base URL")) self.label_9.setText(_translate("addVendorDialog", "Third party provider"))
self.label_7.setText(_translate("addVendorDialog", "Description"))
self.label_6.setText(_translate("addVendorDialog", "Platform (optional)"))
self.label_9.setText(_translate("addVendorDialog", "External Companies"))
self.label_5.setText(_translate("addVendorDialog", "API Key (optional)"))
self.label_4.setText(_translate("addVendorDialog", "Requestor ID (oprtional)"))
self.label_8.setText(_translate("addVendorDialog", "Local Only Vendor"))
self.url_validation_label.setText(_translate("addVendorDialog", "Validation label")) 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

180
ui/AddVendorDialog.ui

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>600</width> <width>600</width>
<height>548</height> <height>620</height>
</rect> </rect>
</property> </property>
<property name="font"> <property name="font">
@ -35,30 +35,10 @@
<property name="spacing"> <property name="spacing">
<number>20</number> <number>20</number>
</property> </property>
<item row="1" column="1"> <item row="9" column="0" alignment="Qt::AlignTop">
<widget class="QLabel" name="name_validation_label"> <widget class="QLabel" name="label_7">
<property name="text">
<string>Validation label</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="2" column="1">
<widget class="QLineEdit" name="baseUrlEdit"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="nameEdit"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Customer ID</string> <string>Description</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -69,77 +49,151 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0" alignment="Qt::AlignTop"> <item row="6" column="0">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Description</string> <string>API Key</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="1"> <item row="10" column="1">
<widget class="QPlainTextEdit" name="companiesEdit"/> <widget class="QPlainTextEdit" name="companiesEdit"/>
</item> </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"> <item row="7" column="0">
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
<string>Platform (optional)</string> <string>Platform</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0" alignment="Qt::AlignTop"> <item row="8" column="1">
<widget class="QLabel" name="label_9"> <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"> <property name="text">
<string>External Companies</string> <string/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item>
<widget class="QLineEdit" name="customerIdEdit"/> <spacer name="horizontalSpacer">
</item> <property name="orientation">
<item row="6" column="1"> <enum>Qt::Horizontal</enum>
<widget class="QLineEdit" name="apiKeyEdit"/> </property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item> </item>
<item row="6" column="0"> <item>
<widget class="QLabel" name="label_5"> <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"> <property name="text">
<string>API Key (optional)</string> <string/>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/help_icon.png</normaloff>:/ui/resources/help_icon.png</iconset>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> </layout>
<widget class="QLineEdit" name="platformEdit"/> </widget>
</item> </item>
<item row="9" column="1"> <item row="8" column="0">
<widget class="QPlainTextEdit" name="descriptionEdit"/> <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>
<item row="5" column="1"> <item row="5" column="1">
<widget class="QLineEdit" name="requestorIdEdit"/> <widget class="QLineEdit" name="requestorIdEdit"/>
</item> </item>
<item row="5" column="0"> <item row="4" column="1">
<widget class="QLabel" name="label_4"> <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"> <property name="text">
<string>Requestor ID (oprtional)</string> <string>Third party provider</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="0"> <item row="3" column="1">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="url_validation_label">
<property name="text"> <property name="text">
<string>Local Only Vendor</string> <string>Validation label</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1"> <item row="2" column="1">
<widget class="QCheckBox" name="local_only_check_box"> <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"> <property name="text">
<string/> <string>Name</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="7" column="1">
<widget class="QLabel" name="url_validation_label"> <widget class="QLineEdit" name="platformEdit"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>Validation label</string> <string>Requestor ID</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -148,6 +202,20 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<resources/> <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/> <connections/>
</ui> </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>

9
ui/FetchProgressDialog.py

@ -2,16 +2,18 @@
# Form implementation generated from reading ui file 'FetchProgressDialog.ui' # Form implementation generated from reading ui file 'FetchProgressDialog.ui'
# #
# Created by: PyQt5 UI code generator 5.9.2 # Created by: PyQt5 UI code generator 5.12.3
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_FetchProgressDialog(object): class Ui_FetchProgressDialog(object):
def setupUi(self, FetchProgressDialog): def setupUi(self, FetchProgressDialog):
FetchProgressDialog.setObjectName("FetchProgressDialog") FetchProgressDialog.setObjectName("FetchProgressDialog")
FetchProgressDialog.resize(680, 353) FetchProgressDialog.resize(800, 600)
FetchProgressDialog.setMinimumSize(QtCore.QSize(680, 0)) FetchProgressDialog.setMinimumSize(QtCore.QSize(680, 0))
font = QtGui.QFont() font = QtGui.QFont()
font.setPointSize(9) font.setPointSize(9)
@ -57,7 +59,7 @@ class Ui_FetchProgressDialog(object):
self.results_scroll_area.setWidgetResizable(True) self.results_scroll_area.setWidgetResizable(True)
self.results_scroll_area.setObjectName("results_scroll_area") self.results_scroll_area.setObjectName("results_scroll_area")
self.scroll_area_widget_contents = QtWidgets.QWidget() self.scroll_area_widget_contents = QtWidgets.QWidget()
self.scroll_area_widget_contents.setGeometry(QtCore.QRect(0, 0, 660, 236)) 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_widget_contents.setObjectName("scroll_area_widget_contents")
self.scroll_area_vertical_layout = QtWidgets.QVBoxLayout(self.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.scroll_area_vertical_layout.setObjectName("scroll_area_vertical_layout")
@ -76,4 +78,3 @@ class Ui_FetchProgressDialog(object):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
FetchProgressDialog.setWindowTitle(_translate("FetchProgressDialog", "Fetch Progress")) FetchProgressDialog.setWindowTitle(_translate("FetchProgressDialog", "Fetch Progress"))
self.status_label.setText(_translate("FetchProgressDialog", "Fetching...")) self.status_label.setText(_translate("FetchProgressDialog", "Fetching..."))

8
ui/FetchProgressDialog.ui

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>680</width> <width>800</width>
<height>353</height> <height>600</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
@ -88,8 +88,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>660</width> <width>780</width>
<height>236</height> <height>480</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="scroll_area_vertical_layout"/> <layout class="QVBoxLayout" name="scroll_area_vertical_layout"/>

0
ui/FetchProgressDialog_bak.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>

1141
ui/MainWindow.py

File diff suppressed because it is too large Load Diff

1982
ui/MainWindow.ui

File diff suppressed because it is too large Load Diff

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>

5
ui/MessageDialog.py

@ -21,7 +21,12 @@ class Ui_message_dialog(object):
self.message_label.setAlignment(QtCore.Qt.AlignCenter) self.message_label.setAlignment(QtCore.Qt.AlignCenter)
self.message_label.setObjectName("message_label") self.message_label.setObjectName("message_label")
self.verticalLayout.addWidget(self.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) self.retranslateUi(message_dialog)
QtCore.QMetaObject.connectSlotsByName(message_dialog) QtCore.QMetaObject.connectSlotsByName(message_dialog)

7
ui/MessageDialog.ui

@ -29,6 +29,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

7
ui/ReportResultWidget.py

@ -73,16 +73,12 @@ class Ui_ReportResultWidget(object):
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth())
self.frame_2.setSizePolicy(sizePolicy) self.frame_2.setSizePolicy(sizePolicy)
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2") self.frame_2.setObjectName("frame_2")
self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_2) self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_2)
self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(6) self.verticalLayout.setSpacing(6)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.file_frame = QtWidgets.QFrame(self.frame_2) self.file_frame = QtWidgets.QFrame(self.frame_2)
self.file_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.file_frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.file_frame.setObjectName("file_frame") self.file_frame.setObjectName("file_frame")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.file_frame) self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.file_frame)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
@ -109,7 +105,7 @@ class Ui_ReportResultWidget(object):
self.folder_button.setSizePolicy(sizePolicy) self.folder_button.setSizePolicy(sizePolicy)
self.folder_button.setText("") self.folder_button.setText("")
icon = QtGui.QIcon() icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("resources/folder_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap(":/ui/resources/folder_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.folder_button.setIcon(icon) self.folder_button.setIcon(icon)
self.folder_button.setObjectName("folder_button") self.folder_button.setObjectName("folder_button")
self.horizontalLayout_4.addWidget(self.folder_button) self.horizontalLayout_4.addWidget(self.folder_button)
@ -193,3 +189,4 @@ class Ui_ReportResultWidget(object):
self.message_label.setText(_translate("ReportResultWidget", "No exception messages")) self.message_label.setText(_translate("ReportResultWidget", "No exception messages"))
self.success_label.setText(_translate("ReportResultWidget", "Failed!")) self.success_label.setText(_translate("ReportResultWidget", "Failed!"))
self.label_6.setText(_translate("ReportResultWidget", "Retry")) self.label_6.setText(_translate("ReportResultWidget", "Retry"))
import Resources_rc

20
ui/ReportResultWidget.ui

@ -145,12 +145,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing"> <property name="spacing">
<number>6</number> <number>6</number>
@ -169,12 +163,6 @@
</property> </property>
<item> <item>
<widget class="QFrame" name="file_frame"> <widget class="QFrame" name="file_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
@ -227,8 +215,8 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset> <iconset resource="../Resources.qrc">
<normaloff>resources/folder_icon.png</normaloff>resources/folder_icon.png</iconset> <normaloff>:/ui/resources/folder_icon.png</normaloff>:/ui/resources/folder_icon.png</iconset>
</property> </property>
</widget> </widget>
</item> </item>
@ -361,6 +349,8 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<resources/> <resources>
<include location="../Resources.qrc"/>
</resources>
<connections/> <connections/>
</ui> </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>

89
ui/SearchAndFrame.py

@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'SearchAndFrame.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(338, 256)
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.NoFrame)
search_and_clause_parameter_frame.setFrameShadow(QtWidgets.QFrame.Plain)
self.verticalLayout = QtWidgets.QVBoxLayout(search_and_clause_parameter_frame)
self.verticalLayout.setObjectName("verticalLayout")
self.search_and_label = QtWidgets.QLabel(search_and_clause_parameter_frame)
self.search_and_label.setMaximumSize(QtCore.QSize(16777215, 22))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.search_and_label.setFont(font)
self.search_and_label.setAlignment(QtCore.Qt.AlignCenter)
self.search_and_label.setObjectName("search_and_label")
self.verticalLayout.addWidget(self.search_and_label)
self.search_and_clause_body_frame = QtWidgets.QFrame(search_and_clause_parameter_frame)
self.search_and_clause_body_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.search_and_clause_body_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
self.search_and_clause_body_frame.setObjectName("search_and_clause_body_frame")
self.gridLayout = QtWidgets.QGridLayout(self.search_and_clause_body_frame)
self.gridLayout.setObjectName("gridLayout")
self.search_add_or_clause_button = QtWidgets.QPushButton(self.search_and_clause_body_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, 0, 1, 1, 1)
self.search_remove_and_clause_button = QtWidgets.QPushButton(self.search_and_clause_body_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, 1, 1, 1, 1)
self.search_or_clause_parameters_frame = QtWidgets.QFrame(self.search_and_clause_body_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.NoFrame)
self.search_or_clause_parameters_frame.setFrameShadow(QtWidgets.QFrame.Plain)
self.search_or_clause_parameters_frame.setObjectName("search_or_clause_parameters_frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.search_or_clause_parameters_frame)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout.addWidget(self.search_or_clause_parameters_frame, 0, 0, 2, 1)
self.verticalLayout.addWidget(self.search_and_clause_body_frame)
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_and_label.setText(_translate("search_and_clause_parameter_frame", "AND"))
self.search_add_or_clause_button.setText(_translate("search_and_clause_parameter_frame", "Add \"Or\""))
self.search_remove_and_clause_button.setText(_translate("search_and_clause_parameter_frame", "Remove \"And\""))
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_())

111
ui/SearchAndFrame.ui

@ -0,0 +1,111 @@
<?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>338</width>
<height>256</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::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="search_and_label">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>AND</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="search_and_clause_body_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<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;</string>
</property>
</widget>
</item>
<item row="1" 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;</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="2">
<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::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2"/>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

90
ui/SearchOrFrame.py

@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'SearchOrFrame.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_or_clause_parameter_frame(object):
def setupUi(self, search_or_clause_parameter_frame):
search_or_clause_parameter_frame.setObjectName("search_or_clause_parameter_frame")
search_or_clause_parameter_frame.resize(842, 101)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(search_or_clause_parameter_frame.sizePolicy().hasHeightForWidth())
search_or_clause_parameter_frame.setSizePolicy(sizePolicy)
search_or_clause_parameter_frame.setFrameShape(QtWidgets.QFrame.NoFrame)
search_or_clause_parameter_frame.setFrameShadow(QtWidgets.QFrame.Plain)
self.horizontalLayout = QtWidgets.QHBoxLayout(search_or_clause_parameter_frame)
self.horizontalLayout.setObjectName("horizontalLayout")
self.search_or_label = QtWidgets.QLabel(search_or_clause_parameter_frame)
self.search_or_label.setMaximumSize(QtCore.QSize(16777215, 22))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.search_or_label.setFont(font)
self.search_or_label.setAutoFillBackground(False)
self.search_or_label.setAlignment(QtCore.Qt.AlignCenter)
self.search_or_label.setObjectName("search_or_label")
self.horizontalLayout.addWidget(self.search_or_label)
self.search_field_parameter_combobox = QtWidgets.QComboBox(search_or_clause_parameter_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_field_parameter_combobox.sizePolicy().hasHeightForWidth())
self.search_field_parameter_combobox.setSizePolicy(sizePolicy)
self.search_field_parameter_combobox.setObjectName("search_field_parameter_combobox")
self.horizontalLayout.addWidget(self.search_field_parameter_combobox)
self.search_comparison_parameter_combobox = QtWidgets.QComboBox(search_or_clause_parameter_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_comparison_parameter_combobox.sizePolicy().hasHeightForWidth())
self.search_comparison_parameter_combobox.setSizePolicy(sizePolicy)
self.search_comparison_parameter_combobox.setObjectName("search_comparison_parameter_combobox")
self.horizontalLayout.addWidget(self.search_comparison_parameter_combobox)
self.search_type_label = QtWidgets.QLabel(search_or_clause_parameter_frame)
self.search_type_label.setObjectName("search_type_label")
self.horizontalLayout.addWidget(self.search_type_label)
self.search_value_parameter_lineedit = QtWidgets.QLineEdit(search_or_clause_parameter_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_value_parameter_lineedit.sizePolicy().hasHeightForWidth())
self.search_value_parameter_lineedit.setSizePolicy(sizePolicy)
self.search_value_parameter_lineedit.setObjectName("search_value_parameter_lineedit")
self.horizontalLayout.addWidget(self.search_value_parameter_lineedit)
self.search_remove_or_clause_button = QtWidgets.QPushButton(search_or_clause_parameter_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_remove_or_clause_button.sizePolicy().hasHeightForWidth())
self.search_remove_or_clause_button.setSizePolicy(sizePolicy)
self.search_remove_or_clause_button.setObjectName("search_remove_or_clause_button")
self.horizontalLayout.addWidget(self.search_remove_or_clause_button)
self.retranslateUi(search_or_clause_parameter_frame)
QtCore.QMetaObject.connectSlotsByName(search_or_clause_parameter_frame)
def retranslateUi(self, search_or_clause_parameter_frame):
_translate = QtCore.QCoreApplication.translate
search_or_clause_parameter_frame.setWindowTitle(_translate("search_or_clause_parameter_frame", "Frame"))
self.search_or_label.setText(_translate("search_or_clause_parameter_frame", "OR"))
self.search_type_label.setText(_translate("search_or_clause_parameter_frame", "Type"))
self.search_remove_or_clause_button.setText(_translate("search_or_clause_parameter_frame", "Remove \"Or\""))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
search_or_clause_parameter_frame = QtWidgets.QFrame()
ui = Ui_search_or_clause_parameter_frame()
ui.setupUi(search_or_clause_parameter_frame)
search_or_clause_parameter_frame.show()
sys.exit(app.exec_())

109
ui/SearchOrFrame.ui

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>search_or_clause_parameter_frame</class>
<widget class="QFrame" name="search_or_clause_parameter_frame">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>842</width>
<height>101</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::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="search_or_label">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>22</height>
</size>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string>OR</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="search_field_parameter_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="search_comparison_parameter_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="search_type_label">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="search_value_parameter_lineedit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="search_remove_or_clause_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove &quot;Or&quot;</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

165
ui/SearchTab.py

@ -0,0 +1,165 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'SearchTab.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_tab(object):
def setupUi(self, search_tab):
search_tab.setObjectName("search_tab")
search_tab.resize(913, 578)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/tab_icons/search_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
search_tab.setWindowIcon(icon)
self.verticalLayout = QtWidgets.QVBoxLayout(search_tab)
self.verticalLayout.setObjectName("verticalLayout")
self.search_parameters_frame = QtWidgets.QFrame(search_tab)
self.search_parameters_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.search_parameters_frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.search_parameters_frame.setObjectName("search_parameters_frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.search_parameters_frame)
self.gridLayout_2.setObjectName("gridLayout_2")
self.search_and_clause_parameters_scrollarea = QtWidgets.QScrollArea(self.search_parameters_frame)
self.search_and_clause_parameters_scrollarea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.search_and_clause_parameters_scrollarea.setWidgetResizable(True)
self.search_and_clause_parameters_scrollarea.setObjectName("search_and_clause_parameters_scrollarea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 778, 176))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.scrollAreaWidgetContents.sizePolicy().hasHeightForWidth())
self.scrollAreaWidgetContents.setSizePolicy(sizePolicy)
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.formLayout_8 = QtWidgets.QFormLayout(self.scrollAreaWidgetContents)
self.formLayout_8.setObjectName("formLayout_8")
self.search_and_clause_parameters_scrollarea.setWidget(self.scrollAreaWidgetContents)
self.gridLayout_2.addWidget(self.search_and_clause_parameters_scrollarea, 4, 0, 1, 5)
self.search_start_year_parameter_dateedit = QtWidgets.QDateEdit(self.search_parameters_frame)
self.search_start_year_parameter_dateedit.setObjectName("search_start_year_parameter_dateedit")
self.gridLayout_2.addWidget(self.search_start_year_parameter_dateedit, 3, 1, 1, 1)
self.search_add_and_button = QtWidgets.QPushButton(self.search_parameters_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_add_and_button.sizePolicy().hasHeightForWidth())
self.search_add_and_button.setSizePolicy(sizePolicy)
self.search_add_and_button.setObjectName("search_add_and_button")
self.gridLayout_2.addWidget(self.search_add_and_button, 3, 4, 1, 1)
spacerItem = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_2.addItem(spacerItem, 3, 3, 1, 1)
self.search_report_parameter_combobox = QtWidgets.QComboBox(self.search_parameters_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_report_parameter_combobox.sizePolicy().hasHeightForWidth())
self.search_report_parameter_combobox.setSizePolicy(sizePolicy)
self.search_report_parameter_combobox.setObjectName("search_report_parameter_combobox")
self.gridLayout_2.addWidget(self.search_report_parameter_combobox, 3, 0, 1, 1)
self.search_report_parameter_label = QtWidgets.QLabel(self.search_parameters_frame)
self.search_report_parameter_label.setObjectName("search_report_parameter_label")
self.gridLayout_2.addWidget(self.search_report_parameter_label, 1, 0, 1, 1)
self.search_start_year_parameter_label = QtWidgets.QLabel(self.search_parameters_frame)
self.search_start_year_parameter_label.setObjectName("search_start_year_parameter_label")
self.gridLayout_2.addWidget(self.search_start_year_parameter_label, 1, 1, 1, 1)
self.search_end_year_parameter_label = QtWidgets.QLabel(self.search_parameters_frame)
self.search_end_year_parameter_label.setObjectName("search_end_year_parameter_label")
self.gridLayout_2.addWidget(self.search_end_year_parameter_label, 1, 2, 1, 1)
self.search_end_year_parameter_dateedit = QtWidgets.QDateEdit(self.search_parameters_frame)
self.search_end_year_parameter_dateedit.setObjectName("search_end_year_parameter_dateedit")
self.gridLayout_2.addWidget(self.search_end_year_parameter_dateedit, 3, 2, 1, 1)
self.verticalLayout.addWidget(self.search_parameters_frame)
self.search_control_frame = QtWidgets.QFrame(search_tab)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_control_frame.sizePolicy().hasHeightForWidth())
self.search_control_frame.setSizePolicy(sizePolicy)
self.search_control_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.search_control_frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.search_control_frame.setObjectName("search_control_frame")
self.gridLayout = QtWidgets.QGridLayout(self.search_control_frame)
self.gridLayout.setObjectName("gridLayout")
self.search_export_button = QtWidgets.QPushButton(self.search_control_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_export_button.sizePolicy().hasHeightForWidth())
self.search_export_button.setSizePolicy(sizePolicy)
self.search_export_button.setObjectName("search_export_button")
self.gridLayout.addWidget(self.search_export_button, 1, 0, 1, 1)
self.search_button = QtWidgets.QPushButton(self.search_control_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_button.sizePolicy().hasHeightForWidth())
self.search_button.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.search_button.setFont(font)
self.search_button.setObjectName("search_button")
self.gridLayout.addWidget(self.search_button, 0, 3, 2, 1)
self.search_import_button = QtWidgets.QPushButton(self.search_control_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_import_button.sizePolicy().hasHeightForWidth())
self.search_import_button.setSizePolicy(sizePolicy)
self.search_import_button.setObjectName("search_import_button")
self.gridLayout.addWidget(self.search_import_button, 0, 0, 1, 1)
self.search_open_file_checkbox = QtWidgets.QCheckBox(self.search_control_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_open_file_checkbox.sizePolicy().hasHeightForWidth())
self.search_open_file_checkbox.setSizePolicy(sizePolicy)
self.search_open_file_checkbox.setChecked(True)
self.search_open_file_checkbox.setTristate(False)
self.search_open_file_checkbox.setObjectName("search_open_file_checkbox")
self.gridLayout.addWidget(self.search_open_file_checkbox, 0, 2, 1, 1)
self.search_open_folder_checkbox = QtWidgets.QCheckBox(self.search_control_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.search_open_folder_checkbox.sizePolicy().hasHeightForWidth())
self.search_open_folder_checkbox.setSizePolicy(sizePolicy)
self.search_open_folder_checkbox.setObjectName("search_open_folder_checkbox")
self.gridLayout.addWidget(self.search_open_folder_checkbox, 1, 2, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem1, 0, 1, 2, 1)
self.verticalLayout.addWidget(self.search_control_frame)
self.retranslateUi(search_tab)
QtCore.QMetaObject.connectSlotsByName(search_tab)
def retranslateUi(self, search_tab):
_translate = QtCore.QCoreApplication.translate
search_tab.setWindowTitle(_translate("search_tab", "Search"))
self.search_start_year_parameter_dateedit.setDisplayFormat(_translate("search_tab", "yyyy"))
self.search_add_and_button.setText(_translate("search_tab", "Add \"And\""))
self.search_report_parameter_label.setText(_translate("search_tab", "Report"))
self.search_start_year_parameter_label.setText(_translate("search_tab", "Start Year"))
self.search_end_year_parameter_label.setText(_translate("search_tab", "End Year"))
self.search_end_year_parameter_dateedit.setDisplayFormat(_translate("search_tab", "yyyy"))
self.search_export_button.setText(_translate("search_tab", "Export Search"))
self.search_button.setText(_translate("search_tab", "Search"))
self.search_import_button.setText(_translate("search_tab", "Import Search"))
self.search_open_file_checkbox.setText(_translate("search_tab", "Open File"))
self.search_open_folder_checkbox.setText(_translate("search_tab", "Open Folder"))
import Resources_rc
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
search_tab = QtWidgets.QWidget()
ui = Ui_search_tab()
ui.setupUi(search_tab)
search_tab.show()
sys.exit(app.exec_())

248
ui/SearchTab.ui

@ -0,0 +1,248 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>search_tab</class>
<widget class="QWidget" name="search_tab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>913</width>
<height>578</height>
</rect>
</property>
<property name="windowTitle">
<string>Search</string>
</property>
<property name="windowIcon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/tab_icons/search_icon.png</normaloff>:/ui/resources/tab_icons/search_icon.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="search_parameters_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="0" colspan="5">
<widget class="QScrollArea" name="search_and_clause_parameters_scrollarea">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>778</width>
<height>176</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QFormLayout" name="formLayout_8"/>
</widget>
</widget>
</item>
<item row="3" column="1">
<widget class="QDateEdit" name="search_start_year_parameter_dateedit">
<property name="displayFormat">
<string>yyyy</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QPushButton" name="search_add_and_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add &quot;And&quot;</string>
</property>
</widget>
</item>
<item row="3" column="3">
<spacer name="search_initial_parameters_spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QComboBox" name="search_report_parameter_combobox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="search_report_parameter_label">
<property name="text">
<string>Report</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="search_start_year_parameter_label">
<property name="text">
<string>Start Year</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="search_end_year_parameter_label">
<property name="text">
<string>End Year</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QDateEdit" name="search_end_year_parameter_dateedit">
<property name="displayFormat">
<string>yyyy</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="search_control_frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<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="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QPushButton" name="search_export_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Export Search</string>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="2">
<widget class="QPushButton" name="search_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Search</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="search_import_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Import Search</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="search_open_file_checkbox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Open File</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="search_open_folder_checkbox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Open Folder</string>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="2">
<spacer name="search_control_spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

386
ui/SettingsTab.py

@ -0,0 +1,386 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'SettingsTab.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_settings_tab(object):
def setupUi(self, settings_tab):
settings_tab.setObjectName("settings_tab")
settings_tab.resize(852, 507)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/ui/resources/tab_icons/settings_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
settings_tab.setWindowIcon(icon)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(settings_tab)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.scrollArea = QtWidgets.QScrollArea(settings_tab)
self.scrollArea.setFocusPolicy(QtCore.Qt.StrongFocus)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 815, 596))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.scrollAreaWidgetContents)
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 2)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
spacerItem = QtWidgets.QSpacerItem(120, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem)
self.frame_4 = QtWidgets.QFrame(self.scrollAreaWidgetContents)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_4.sizePolicy().hasHeightForWidth())
self.frame_4.setSizePolicy(sizePolicy)
self.frame_4.setObjectName("frame_4")
self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_4)
self.verticalLayout.setObjectName("verticalLayout")
self.frame_2 = QtWidgets.QFrame(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, 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.StyledPanel)
self.frame_2.setObjectName("frame_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.frame_2)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.label_27 = QtWidgets.QLabel(self.frame_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_27.sizePolicy().hasHeightForWidth())
self.label_27.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.label_27.setFont(font)
self.label_27.setObjectName("label_27")
self.verticalLayout_2.addWidget(self.label_27, 0, QtCore.Qt.AlignHCenter)
self.frame_3 = QtWidgets.QFrame(self.frame_2)
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.setObjectName("frame_3")
self.gridLayout = QtWidgets.QGridLayout(self.frame_3)
self.gridLayout.setHorizontalSpacing(10)
self.gridLayout.setObjectName("gridLayout")
self.label = QtWidgets.QLabel(self.frame_3)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.show_debug_check_box = QtWidgets.QCheckBox(self.frame_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.show_debug_check_box.sizePolicy().hasHeightForWidth())
self.show_debug_check_box.setSizePolicy(sizePolicy)
self.show_debug_check_box.setText("")
self.show_debug_check_box.setObjectName("show_debug_check_box")
self.gridLayout.addWidget(self.show_debug_check_box, 0, 1, 1, 1)
self.verticalLayout_2.addWidget(self.frame_3)
self.verticalLayout.addWidget(self.frame_2)
self.frame_33 = QtWidgets.QFrame(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_33.sizePolicy().hasHeightForWidth())
self.frame_33.setSizePolicy(sizePolicy)
self.frame_33.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_33.setObjectName("frame_33")
self.verticalLayout_19 = QtWidgets.QVBoxLayout(self.frame_33)
self.verticalLayout_19.setObjectName("verticalLayout_19")
self.label_24 = QtWidgets.QLabel(self.frame_33)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_24.sizePolicy().hasHeightForWidth())
self.label_24.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.label_24.setFont(font)
self.label_24.setObjectName("label_24")
self.verticalLayout_19.addWidget(self.label_24, 0, QtCore.Qt.AlignHCenter)
self.frame_34 = QtWidgets.QFrame(self.frame_33)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame_34.sizePolicy().hasHeightForWidth())
self.frame_34.setSizePolicy(sizePolicy)
self.frame_34.setObjectName("frame_34")
self.gridLayout_11 = QtWidgets.QGridLayout(self.frame_34)
self.gridLayout_11.setHorizontalSpacing(10)
self.gridLayout_11.setObjectName("gridLayout_11")
self.other_directory_help_button = QtWidgets.QPushButton(self.frame_34)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.other_directory_help_button.sizePolicy().hasHeightForWidth())
self.other_directory_help_button.setSizePolicy(sizePolicy)
self.other_directory_help_button.setText("")
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/ui/resources/help_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.other_directory_help_button.setIcon(icon1)
self.other_directory_help_button.setObjectName("other_directory_help_button")
self.gridLayout_11.addWidget(self.other_directory_help_button, 1, 3, 1, 1)
self.other_directory_button = QtWidgets.QPushButton(self.frame_34)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/ui/resources/folder_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.other_directory_button.setIcon(icon2)
self.other_directory_button.setObjectName("other_directory_button")
self.gridLayout_11.addWidget(self.other_directory_button, 1, 2, 1, 1)
self.request_timeout_help_button = QtWidgets.QPushButton(self.frame_34)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.request_timeout_help_button.sizePolicy().hasHeightForWidth())
self.request_timeout_help_button.setSizePolicy(sizePolicy)
self.request_timeout_help_button.setText("")
self.request_timeout_help_button.setIcon(icon1)
self.request_timeout_help_button.setObjectName("request_timeout_help_button")
self.gridLayout_11.addWidget(self.request_timeout_help_button, 6, 2, 1, 1)
self.concurrent_vendors_help_button = QtWidgets.QPushButton(self.frame_34)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.concurrent_vendors_help_button.sizePolicy().hasHeightForWidth())
self.concurrent_vendors_help_button.setSizePolicy(sizePolicy)
self.concurrent_vendors_help_button.setText("")
self.concurrent_vendors_help_button.setIcon(icon1)
self.concurrent_vendors_help_button.setObjectName("concurrent_vendors_help_button")
self.gridLayout_11.addWidget(self.concurrent_vendors_help_button, 7, 2, 1, 1)
self.label_37 = QtWidgets.QLabel(self.frame_34)
self.label_37.setObjectName("label_37")
self.gridLayout_11.addWidget(self.label_37, 6, 0, 1, 1)
self.user_agent_edit = QtWidgets.QLineEdit(self.frame_34)
self.user_agent_edit.setObjectName("user_agent_edit")
self.gridLayout_11.addWidget(self.user_agent_edit, 10, 1, 1, 1)
self.other_directory_edit = QtWidgets.QLineEdit(self.frame_34)
self.other_directory_edit.setReadOnly(True)
self.other_directory_edit.setObjectName("other_directory_edit")
self.gridLayout_11.addWidget(self.other_directory_edit, 1, 1, 1, 1)
self.label_32 = QtWidgets.QLabel(self.frame_34)
self.label_32.setObjectName("label_32")
self.gridLayout_11.addWidget(self.label_32, 8, 0, 1, 1)
self.yearly_directory_help_button = QtWidgets.QPushButton(self.frame_34)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.yearly_directory_help_button.sizePolicy().hasHeightForWidth())
self.yearly_directory_help_button.setSizePolicy(sizePolicy)
self.yearly_directory_help_button.setText("")
self.yearly_directory_help_button.setIcon(icon1)
self.yearly_directory_help_button.setObjectName("yearly_directory_help_button")
self.gridLayout_11.addWidget(self.yearly_directory_help_button, 0, 3, 1, 1)
self.request_interval_spin_box = QtWidgets.QSpinBox(self.frame_34)
self.request_interval_spin_box.setMaximum(999)
self.request_interval_spin_box.setObjectName("request_interval_spin_box")
self.gridLayout_11.addWidget(self.request_interval_spin_box, 5, 1, 1, 1)
self.label_25 = QtWidgets.QLabel(self.frame_34)
self.label_25.setObjectName("label_25")
self.gridLayout_11.addWidget(self.label_25, 0, 0, 1, 1)
self.request_interval_help_button = QtWidgets.QPushButton(self.frame_34)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.request_interval_help_button.sizePolicy().hasHeightForWidth())
self.request_interval_help_button.setSizePolicy(sizePolicy)
self.request_interval_help_button.setText("")
self.request_interval_help_button.setIcon(icon1)
self.request_interval_help_button.setObjectName("request_interval_help_button")
self.gridLayout_11.addWidget(self.request_interval_help_button, 5, 2, 1, 1)
self.request_timeout_spin_box = QtWidgets.QSpinBox(self.frame_34)
self.request_timeout_spin_box.setMaximum(9999)
self.request_timeout_spin_box.setSingleStep(30)
self.request_timeout_spin_box.setObjectName("request_timeout_spin_box")
self.gridLayout_11.addWidget(self.request_timeout_spin_box, 6, 1, 1, 1)
self.yearly_directory_button = QtWidgets.QPushButton(self.frame_34)
self.yearly_directory_button.setIcon(icon2)
self.yearly_directory_button.setObjectName("yearly_directory_button")
self.gridLayout_11.addWidget(self.yearly_directory_button, 0, 2, 1, 1)
self.concurrent_reports_spin_box = QtWidgets.QSpinBox(self.frame_34)
self.concurrent_reports_spin_box.setMaximum(999)
self.concurrent_reports_spin_box.setObjectName("concurrent_reports_spin_box")
self.gridLayout_11.addWidget(self.concurrent_reports_spin_box, 8, 1, 1, 1)
self.label_31 = QtWidgets.QLabel(self.frame_34)
self.label_31.setObjectName("label_31")
self.gridLayout_11.addWidget(self.label_31, 7, 0, 1, 1)
self.yearly_directory_edit = QtWidgets.QLineEdit(self.frame_34)
self.yearly_directory_edit.setReadOnly(True)
self.yearly_directory_edit.setObjectName("yearly_directory_edit")
self.gridLayout_11.addWidget(self.yearly_directory_edit, 0, 1, 1, 1)
self.label_73 = QtWidgets.QLabel(self.frame_34)
self.label_73.setObjectName("label_73")
self.gridLayout_11.addWidget(self.label_73, 10, 0, 1, 1)
self.user_agent_help_button = QtWidgets.QPushButton(self.frame_34)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.user_agent_help_button.sizePolicy().hasHeightForWidth())
self.user_agent_help_button.setSizePolicy(sizePolicy)
self.user_agent_help_button.setText("")
self.user_agent_help_button.setIcon(icon1)
self.user_agent_help_button.setObjectName("user_agent_help_button")
self.gridLayout_11.addWidget(self.user_agent_help_button, 10, 2, 1, 1)
self.concurrent_reports_help_button = QtWidgets.QPushButton(self.frame_34)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.concurrent_reports_help_button.sizePolicy().hasHeightForWidth())
self.concurrent_reports_help_button.setSizePolicy(sizePolicy)
self.concurrent_reports_help_button.setText("")
self.concurrent_reports_help_button.setIcon(icon1)
self.concurrent_reports_help_button.setObjectName("concurrent_reports_help_button")
self.gridLayout_11.addWidget(self.concurrent_reports_help_button, 8, 2, 1, 1)
self.concurrent_vendors_spin_box = QtWidgets.QSpinBox(self.frame_34)
self.concurrent_vendors_spin_box.setMaximum(999)
self.concurrent_vendors_spin_box.setObjectName("concurrent_vendors_spin_box")
self.gridLayout_11.addWidget(self.concurrent_vendors_spin_box, 7, 1, 1, 1)
self.label_29 = QtWidgets.QLabel(self.frame_34)
self.label_29.setObjectName("label_29")
self.gridLayout_11.addWidget(self.label_29, 1, 0, 1, 1)
self.label_30 = QtWidgets.QLabel(self.frame_34)
self.label_30.setObjectName("label_30")
self.gridLayout_11.addWidget(self.label_30, 5, 0, 1, 1)
self.verticalLayout_19.addWidget(self.frame_34)
self.verticalLayout.addWidget(self.frame_33)
self.settings_costs_frame = QtWidgets.QFrame(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.settings_costs_frame.sizePolicy().hasHeightForWidth())
self.settings_costs_frame.setSizePolicy(sizePolicy)
self.settings_costs_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.settings_costs_frame.setFrameShadow(QtWidgets.QFrame.Plain)
self.settings_costs_frame.setObjectName("settings_costs_frame")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.settings_costs_frame)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.settings_costs_label = QtWidgets.QLabel(self.settings_costs_frame)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.settings_costs_label.setFont(font)
self.settings_costs_label.setAlignment(QtCore.Qt.AlignCenter)
self.settings_costs_label.setObjectName("settings_costs_label")
self.verticalLayout_3.addWidget(self.settings_costs_label)
self.settings_costs_items_frame = QtWidgets.QFrame(self.settings_costs_frame)
self.settings_costs_items_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.settings_costs_items_frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.settings_costs_items_frame.setObjectName("settings_costs_items_frame")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.settings_costs_items_frame)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.settings_costs_default_currency_label = QtWidgets.QLabel(self.settings_costs_items_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.settings_costs_default_currency_label.sizePolicy().hasHeightForWidth())
self.settings_costs_default_currency_label.setSizePolicy(sizePolicy)
self.settings_costs_default_currency_label.setObjectName("settings_costs_default_currency_label")
self.horizontalLayout_4.addWidget(self.settings_costs_default_currency_label)
self.settings_costs_default_currency_combobox = QtWidgets.QComboBox(self.settings_costs_items_frame)
self.settings_costs_default_currency_combobox.setEditable(True)
self.settings_costs_default_currency_combobox.setObjectName("settings_costs_default_currency_combobox")
self.horizontalLayout_4.addWidget(self.settings_costs_default_currency_combobox)
self.default_currency_help_button = QtWidgets.QPushButton(self.settings_costs_items_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.default_currency_help_button.sizePolicy().hasHeightForWidth())
self.default_currency_help_button.setSizePolicy(sizePolicy)
self.default_currency_help_button.setText("")
self.default_currency_help_button.setIcon(icon1)
self.default_currency_help_button.setObjectName("default_currency_help_button")
self.horizontalLayout_4.addWidget(self.default_currency_help_button)
self.verticalLayout_3.addWidget(self.settings_costs_items_frame)
self.verticalLayout.addWidget(self.settings_costs_frame)
self.save_button = QtWidgets.QPushButton(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.save_button.sizePolicy().hasHeightForWidth())
self.save_button.setSizePolicy(sizePolicy)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/ui/resources/save_icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.save_button.setIcon(icon3)
self.save_button.setObjectName("save_button")
self.verticalLayout.addWidget(self.save_button, 0, QtCore.Qt.AlignHCenter)
self.settings_search_frame = QtWidgets.QFrame(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.settings_search_frame.sizePolicy().hasHeightForWidth())
self.settings_search_frame.setSizePolicy(sizePolicy)
self.settings_search_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.settings_search_frame.setObjectName("settings_search_frame")
self.verticalLayout_20 = QtWidgets.QVBoxLayout(self.settings_search_frame)
self.verticalLayout_20.setObjectName("verticalLayout_20")
self.settings_search_label = QtWidgets.QLabel(self.settings_search_frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.settings_search_label.sizePolicy().hasHeightForWidth())
self.settings_search_label.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.settings_search_label.setFont(font)
self.settings_search_label.setObjectName("settings_search_label")
self.verticalLayout_20.addWidget(self.settings_search_label, 0, QtCore.Qt.AlignHCenter)
self.settings_rebuild_database_button = QtWidgets.QPushButton(self.settings_search_frame)
self.settings_rebuild_database_button.setObjectName("settings_rebuild_database_button")
self.verticalLayout_20.addWidget(self.settings_rebuild_database_button)
self.verticalLayout.addWidget(self.settings_search_frame)
self.frame = QtWidgets.QFrame(self.frame_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
self.frame.setSizePolicy(sizePolicy)
self.frame.setObjectName("frame")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout.addWidget(self.frame)
self.horizontalLayout_3.addWidget(self.frame_4)
spacerItem1 = QtWidgets.QSpacerItem(120, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(spacerItem1)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.horizontalLayout_2.addWidget(self.scrollArea)
self.retranslateUi(settings_tab)
QtCore.QMetaObject.connectSlotsByName(settings_tab)
def retranslateUi(self, settings_tab):
_translate = QtCore.QCoreApplication.translate
settings_tab.setWindowTitle(_translate("settings_tab", "Settings"))
self.label_27.setText(_translate("settings_tab", "General"))
self.label.setText(_translate("settings_tab", "Show Debug Messages in Console Window"))
self.label_24.setText(_translate("settings_tab", "Reports"))
self.other_directory_button.setText(_translate("settings_tab", "Choose"))
self.label_37.setText(_translate("settings_tab", "Request Timeout"))
self.label_32.setText(_translate("settings_tab", "Concurrent Reports"))
self.label_25.setText(_translate("settings_tab", "Yearly Reports Directory"))
self.yearly_directory_button.setText(_translate("settings_tab", "Choose"))
self.label_31.setText(_translate("settings_tab", "Concurrent Vendors"))
self.label_73.setText(_translate("settings_tab", "User Agent"))
self.label_29.setText(_translate("settings_tab", "Other Reports Directory"))
self.label_30.setText(_translate("settings_tab", "Report Request Interval"))
self.settings_costs_label.setText(_translate("settings_tab", "Costs"))
self.settings_costs_default_currency_label.setText(_translate("settings_tab", "Default Currency"))
self.save_button.setText(_translate("settings_tab", "Save All Changes"))
self.settings_search_label.setText(_translate("settings_tab", "Search"))
self.settings_rebuild_database_button.setText(_translate("settings_tab", "Rebuild Database"))
import Resources_rc

621
ui/SettingsTab.ui

@ -0,0 +1,621 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>settings_tab</class>
<widget class="QWidget" name="settings_tab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>852</width>
<height>507</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<property name="windowIcon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/tab_icons/settings_icon.png</normaloff>:/ui/resources/tab_icons/settings_icon.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>815</width>
<height>596</height>
</rect>
</property>
<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>2</number>
</property>
<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_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="label_27">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>General</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="horizontalSpacing">
<number>10</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Show Debug Messages in Console Window</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="show_debug_check_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_33">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_19">
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="label_24">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Reports</string>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_34">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout_11">
<property name="horizontalSpacing">
<number>10</number>
</property>
<item row="1" column="3">
<widget class="QPushButton" name="other_directory_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>
<item row="1" column="2">
<widget class="QPushButton" name="other_directory_button">
<property name="text">
<string>Choose</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>
<item row="6" column="2">
<widget class="QPushButton" name="request_timeout_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>
<item row="7" column="2">
<widget class="QPushButton" name="concurrent_vendors_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>
<item row="6" column="0">
<widget class="QLabel" name="label_37">
<property name="text">
<string>Request Timeout</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLineEdit" name="user_agent_edit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="other_directory_edit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_32">
<property name="text">
<string>Concurrent Reports</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="yearly_directory_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>
<item row="5" column="1">
<widget class="QSpinBox" name="request_interval_spin_box">
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Yearly Reports Directory</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QPushButton" name="request_interval_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>
<item row="6" column="1">
<widget class="QSpinBox" name="request_timeout_spin_box">
<property name="maximum">
<number>9999</number>
</property>
<property name="singleStep">
<number>30</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="yearly_directory_button">
<property name="text">
<string>Choose</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>
<item row="8" column="1">
<widget class="QSpinBox" name="concurrent_reports_spin_box">
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_31">
<property name="text">
<string>Concurrent Vendors</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="yearly_directory_edit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_73">
<property name="text">
<string>User Agent</string>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QPushButton" name="user_agent_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>
<item row="8" column="2">
<widget class="QPushButton" name="concurrent_reports_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>
<item row="7" column="1">
<widget class="QSpinBox" name="concurrent_vendors_spin_box">
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_29">
<property name="text">
<string>Other Reports Directory</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_30">
<property name="text">
<string>Report Request Interval</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="settings_costs_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::Plain</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="settings_costs_label">
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Costs</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="settings_costs_items_frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="settings_costs_default_currency_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Default Currency</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="settings_costs_default_currency_combobox">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="default_currency_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>
</layout>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="save_button">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Save All Changes</string>
</property>
<property name="icon">
<iconset resource="../Resources.qrc">
<normaloff>:/ui/resources/save_icon.png</normaloff>:/ui/resources/save_icon.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="settings_search_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>
<layout class="QVBoxLayout" name="verticalLayout_20">
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="settings_search_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Segoe UI</family>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Search</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="settings_rebuild_database_button">
<property name="text">
<string>Rebuild Database</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout"/>
</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>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../Resources.qrc"/>
</resources>
<connections/>
</ui>

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

Loading…
Cancel
Save