diff --git a/LDMP/conf.py b/LDMP/conf.py index dcc0fdc11..94db36ddc 100644 --- a/LDMP/conf.py +++ b/LDMP/conf.py @@ -52,6 +52,10 @@ class Setting(enum.Enum): UNKNOWN_AREA_OF_INTEREST = "private/unknown_area_of_interest" PRIOR_LOCALE = "private/prior_locale" + DATE_FILTER_ENABLED = "filters/date_filter_enabled" + FILTER_START_DATE = "filters/start_date" + FILTER_END_DATE = "filters/end_date" + DEBUG = "advanced/debug" BINARIES_ENABLED = "advanced/binaries_enabled" BINARIES_DIR = "advanced/binaries_folder" @@ -116,6 +120,9 @@ class SettingsManager: Setting.CUSTOM_CRS: "epsg:4326", Setting.POLL_REMOTE: True, Setting.DOWNLOAD_RESULTS: True, + Setting.DATE_FILTER_ENABLED: False, + Setting.FILTER_START_DATE: "", + Setting.FILTER_END_DATE: "", Setting.BUFFER_CHECKED: False, Setting.AREA_FROM_OPTION: AreaSetting.COUNTRY_REGION.value, Setting.POINT_X: 0.0, diff --git a/LDMP/dataset_additional_metadata.py b/LDMP/dataset_additional_metadata.py new file mode 100644 index 000000000..e1d7833d1 --- /dev/null +++ b/LDMP/dataset_additional_metadata.py @@ -0,0 +1,27 @@ +import os +from pathlib import Path + +from qgis.PyQt import QtWidgets, uic + +DatasetAdditionalMetadataUi, _ = uic.loadUiType( + str(Path(__file__).parents[0] / "gui/DlgDatasetAdditionalMetadata.ui") +) + +ICON_PATH = os.path.join(os.path.dirname(__file__), "icons") + + +class DataSetAdditionalMetadataDialog(QtWidgets.QDialog, DatasetAdditionalMetadataUi): + dataset: dict + + le_title: QtWidgets.QLineEdit + te_author: QtWidgets.QTextEdit + le_source: QtWidgets.QLineEdit + te_citation: QtWidgets.QTextEdit + + def __init__(self, dataset: dict, parent=None): + super().__init__(parent) + self.setupUi(self) + self.le_title.setText(dataset.get("title", "")) + self.te_author.setPlainText(dataset.get("Data source", "")) + self.le_source.setText(dataset.get("Source", "")) + self.te_citation.setPlainText(dataset.get("Citation", "")) diff --git a/LDMP/download_data.py b/LDMP/download_data.py index ff409e081..64f4dfa90 100644 --- a/LDMP/download_data.py +++ b/LDMP/download_data.py @@ -13,6 +13,7 @@ import json import os +from functools import partial from pathlib import Path import qgis.gui @@ -21,6 +22,7 @@ from . import calculate, conf from .conf import Setting, settings_manager +from .dataset_additional_metadata import DataSetAdditionalMetadataDialog from .jobs.manager import job_manager from .logger import log @@ -185,7 +187,8 @@ def update_data_table(self): # Add "Notes" buttons in cell for row in range(0, len(self.datasets)): btn = QtWidgets.QPushButton(self.tr("Details")) - btn.clicked.connect(self.btn_details) + btn_details = partial(self.btn_details, self.datasets[row]) + btn.clicked.connect(btn_details) self.data_view.setIndexWidget(self.proxy_model.index(row, 8), btn) # Category @@ -227,11 +230,12 @@ def update_data_table(self): self.data_view.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) - def btn_details(self): + def btn_details(self, dataset): # button = self.sender() # index = self.data_view.indexAt(button.pos()) # TODO: Code the details view - pass + dlg = DataSetAdditionalMetadataDialog(dataset) + dlg.exec() def btn_calculate(self): # Note that the super class has several tests in it - if they fail it diff --git a/LDMP/gui/DlgDatasetAdditionalMetadata.ui b/LDMP/gui/DlgDatasetAdditionalMetadata.ui new file mode 100644 index 000000000..3c9e53434 --- /dev/null +++ b/LDMP/gui/DlgDatasetAdditionalMetadata.ui @@ -0,0 +1,133 @@ + + + Dialog + + + + 0 + 0 + 706 + 577 + + + + Additional Metadata + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 694 + 565 + + + + + + + Metadata + + + + + + true + + + + + + + true + + + + + + + true + + + + + + + Title + + + + + + + true + + + + + + + Bibliographical Citation + + + + + + + Author or Publisher + + + + + + + Source Link or Identifier + + + + + + + + + + + + + + + QgsCollapsibleGroupBox + QGroupBox +
qgscollapsiblegroupbox.h
+ 1 +
+
+ + scrollArea + le_title + te_author + + + +
diff --git a/LDMP/gui/WidgetMain.ui b/LDMP/gui/WidgetMain.ui index a1a4eafb3..c16bb0fbf 100644 --- a/LDMP/gui/WidgetMain.ui +++ b/LDMP/gui/WidgetMain.ui @@ -18,7 +18,7 @@ - 0 + 1 @@ -41,7 +41,7 @@ Datasets - + @@ -65,7 +65,7 @@ for running algorithms and their results. Search... - + true @@ -82,6 +82,79 @@ for running algorithms and their results. + + + + + + + Filter by date + + + true + + + false + + + true + + + + + + Start + + + + + + + End + + + + + + + + + + + 0 + 0 + 0 + 2021 + 1 + 1 + + + + + + + + + 0 + 0 + 0 + 2021 + 12 + 1 + + + + + 2021 + 12 + 1 + + + + + + + @@ -154,10 +227,21 @@ for running algorithms and their results. + + QgsCollapsibleGroupBox + QGroupBox +
qgscollapsiblegroupbox.h
+ 1 +
+ + QgsDateTimeEdit + QDateTimeEdit +
qgsdatetimeedit.h
+
QgsFilterLineEdit QLineEdit -
qgis.gui
+
qgsfilterlineedit.h
diff --git a/LDMP/jobs/mvc.py b/LDMP/jobs/mvc.py index 1622af69e..986b4b2ef 100644 --- a/LDMP/jobs/mvc.py +++ b/LDMP/jobs/mvc.py @@ -99,6 +99,13 @@ class JobsSortFilterProxyModel(QtCore.QSortFilterProxyModel): def __init__(self, current_sort_field: SortField, *args, **kwargs): super().__init__(*args, **kwargs) self.current_sort_field = current_sort_field + self.start_date = None + self.end_date = None + + def set_date_filter(self, start_date, end_date): + self.start_date = start_date + self.end_date = end_date + self.invalidateFilter() def filterAcceptsRow(self, source_row: int, source_parent: QtCore.QModelIndex): jobs_model = self.sourceModel() @@ -118,7 +125,20 @@ def filterAcceptsRow(self, source_row: int, source_parent: QtCore.QModelIndex): elif self.type_filter == TypeFilter.VECTOR: matches_type = job.is_vector() - return matches_filter and matches_type + # Date filtering logic + matches_date = True + if self.start_date and self.end_date: + job_start_date = QtCore.QDateTime.fromString( + job.start_date.strftime("%Y-%m-%d %H:%M:%S"), "yyyy-MM-dd HH:mm:ss" + ) + job_end_date = QtCore.QDateTime.fromString( + job.end_date.strftime("%Y-%m-%d %H:%M:%S"), "yyyy-MM-dd HH:mm:ss" + ) + matches_date = ( + job_start_date >= self.start_date and job_end_date <= self.end_date + ) + + return matches_filter and matches_type and matches_date def lessThan(self, left: QtCore.QModelIndex, right: QtCore.QModelIndex) -> bool: model = self.sourceModel() diff --git a/LDMP/main_widget.py b/LDMP/main_widget.py index 74c5a6eb9..596a3a39b 100644 --- a/LDMP/main_widget.py +++ b/LDMP/main_widget.py @@ -119,6 +119,8 @@ def __init__( self.message_bar_sort_filter = None + self.proxy_model = None + job_manager.refreshed_local_state.connect(self.refresh_after_cache_update) job_manager.refreshed_from_remote.connect(self.refresh_after_cache_update) job_manager.downloaded_job_results.connect(self.refresh_after_cache_update) @@ -161,6 +163,53 @@ def __init__( self.pushButton_download.setEnabled(True) self.setWindowTitle(DOCK_TITLE) + date_filter_enabled = settings_manager.get_value(Setting.DATE_FILTER_ENABLED) + + if not date_filter_enabled: + date_filter_enabled = False + + self.date_filter_group.setChecked(date_filter_enabled) + + settings_start_date = settings_manager.get_value(Setting.FILTER_START_DATE) + settings_end_date = settings_manager.get_value(Setting.FILTER_END_DATE) + if settings_start_date != "" and settings_end_date != "": + start_date = QtCore.QDateTime.fromString( + settings_start_date, "yyyy-MM-dd HH:mm:ss" + ) + end_date = QtCore.QDateTime.fromString( + settings_end_date, "yyyy-MM-dd HH:mm:ss" + ) + + self.start_dte.setDateTime(start_date) + self.end_dte.setDateTime(end_date) + + self.date_filter_group.toggled.connect(self.date_filter_group_toggled) + date_filter_enabled = functools.partial(self.date_filter_changed, False) + + self.start_dte.dateChanged.connect(date_filter_enabled) + self.end_dte.dateChanged.connect(date_filter_enabled) + + def date_filter_group_toggled(self, value): + settings_manager.write_value(Setting.DATE_FILTER_ENABLED, value) + self.date_filter_changed(disabled=not value) + + def date_filter_changed(self, disabled=False): + settings_manager.write_value( + Setting.FILTER_START_DATE, + self.start_dte.dateTime().toString("yyyy-MM-dd HH:mm:ss"), + ) + + settings_manager.write_value( + Setting.FILTER_END_DATE, + self.end_dte.dateTime().toString("yyyy-MM-dd HH:mm:ss"), + ) + + start_date = self.start_dte.dateTime() if not disabled else None + end_date = self.end_dte.dateTime() if not disabled else None + + if self.proxy_model: + self.proxy_model.set_date_filter(start_date, end_date) + def setup_datasets_page_gui(self): self.pushButton_refresh.setIcon( QtGui.QIcon(os.path.join(ICON_PATH, "mActionRefresh.svg")) @@ -289,6 +338,8 @@ def refresh_after_cache_update(self): # self.datasets_tv.setModel(model) self.proxy_model = jobs_mvc.JobsSortFilterProxyModel(SortField.DATE) self.type_filter_changed(TypeFilter.ALL) + self.date_filter_changed(disabled=not self.date_filter_group.isChecked()) + self.filter_changed("") action = self.filter_menu.actions()[0] action.setChecked(True)