diff --git a/.gitignore b/.gitignore index de24304..d56d2a5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ build/ dist/ *.egg-info/ +ui diff --git a/xicam/gui/bluesky/central.py b/xicam/gui/bluesky/central.py index 4b8f0a2..b76b9ba 100644 --- a/xicam/gui/bluesky/central.py +++ b/xicam/gui/bluesky/central.py @@ -9,6 +9,7 @@ from .search import SearchWidget, SearchState from xicam.gui.bluesky.summary import SummaryWidget + from qtpy.QtCore import QDateTime, Qt from qtpy.QtWidgets import ( QWidget, @@ -24,13 +25,13 @@ def __init__(self, *args, catalog, menuBar, zmq_address=None, **kwargs): super().__init__(*args, **kwargs) - # Define models. search_state = SearchState( catalog=catalog) self.search_model = search_state.search_results_model # Define widgets. self.search_widget = SearchWidget() + # self.search_input_widget = SearchInputWidget() self.summary_widget = SummaryWidget() left_pane = QSplitter(Qt.Vertical) @@ -49,23 +50,67 @@ def show_double_clicked_entry(index): # Set models, connect signals, and set initial values. now = time.time() - ONE_WEEK = 60 * 60 * 24 * 7 - self.search_widget.search_results_widget.setModel( - search_state.search_results_model) - self.search_widget.search_input_widget.search_bar.textChanged.connect( - search_state.search_results_model.on_search_text_changed) - self.search_widget.catalog_selection_widget.catalog_list.setModel( - search_state.catalog_selection_model) + ONE_HOUR = 60 * 60 + TODAY = ONE_HOUR * 24 + ONE_WEEK = TODAY * 7 + ONE_MONTH = TODAY * 30 #used for 30 days QRadioButton + + def set_timerange(timerange): + search_state.search_results_model.on_select_range(timerange) + self.search_widget.search_input_widget.since_widget.setDateTime( + QDateTime.fromSecsSinceEpoch(now - timerange)) + self.search_widget.search_input_widget.until_widget.setDateTime( + QDateTime.fromSecsSinceEpoch(now)) + + def on_select_today(): + set_timerange(TODAY) + self.search_widget.search_input_widget.today_widget.setChecked(True) + + def on_select_lasthour(): + set_timerange(ONE_HOUR) + self.search_widget.search_input_widget.hour_widget.setChecked(True) + + def on_select_30days(): + set_timerange(ONE_MONTH) + self.search_widget.search_input_widget.days_widget.setChecked(True) + + def on_select_all(): + search_state.search_results_model.on_select_all() + self.search_widget.search_input_widget.since_widget.setDateTime( + QDateTime.fromSecsSinceEpoch(0)) + self.search_widget.search_input_widget.until_widget.setDateTime( + QDateTime.fromSecsSinceEpoch(now)) + self.search_widget.search_input_widget.all_widget.setChecked(True) + + # connect QRadioButtons and change date dropdowns (since/until widgets) accordingly + self.search_widget.search_input_widget.today_widget.clicked.connect( + on_select_today) + self.search_widget.search_input_widget.hour_widget.clicked.connect( + on_select_lasthour) + self.search_widget.search_input_widget.days_widget.clicked.connect( + on_select_30days) + self.search_widget.search_input_widget.all_widget.clicked.connect( + on_select_all) + # connect input since/until widgets self.search_widget.search_input_widget.until_widget.dateTimeChanged.connect( search_state.search_results_model.on_until_time_changed) self.search_widget.search_input_widget.until_widget.setDateTime( - QDateTime.fromSecsSinceEpoch(now + ONE_WEEK)) + QDateTime.fromSecsSinceEpoch(now)) self.search_widget.search_input_widget.since_widget.dateTimeChanged.connect( search_state.search_results_model.on_since_time_changed) self.search_widget.search_input_widget.since_widget.setDateTime( QDateTime.fromSecsSinceEpoch(now - ONE_WEEK)) + # connect catalog_list dropdown + self.search_widget.catalog_selection_widget.catalog_list.setModel( + search_state.catalog_selection_model) self.search_widget.catalog_selection_widget.catalog_list.currentIndexChanged.connect( search_state.set_selected_catalog) + + self.search_widget.search_input_widget.search_bar.textChanged.connect( + search_state.search_results_model.on_search_text_changed) + + self.search_widget.search_results_widget.setModel( + search_state.search_results_model) self.search_widget.search_results_widget.selectionModel().selectionChanged.connect( search_state.search_results_model.emit_selected_result) self.search_widget.search_results_widget.doubleClicked.connect( diff --git a/xicam/gui/bluesky/search.py b/xicam/gui/bluesky/search.py index ace77b9..89b140a 100644 --- a/xicam/gui/bluesky/search.py +++ b/xicam/gui/bluesky/search.py @@ -2,7 +2,7 @@ Experimental Qt-based data browser for bluesky """ import ast -from datetime import datetime +from datetime import datetime, date import event_model import functools import itertools @@ -12,15 +12,18 @@ import threading import time + from qtpy.QtCore import Qt, Signal, QThread, QSettings -from qtpy.QtGui import QStandardItemModel, QStandardItem +from qtpy.QtGui import QStandardItemModel, QStandardItem, QButtonGroup from qtpy.QtWidgets import ( QAbstractItemView, QPushButton, + QRadioButton, QComboBox, QDateTimeEdit, QHeaderView, QHBoxLayout, + QGridLayout, QMessageBox, QLabel, QLineEdit, @@ -410,48 +413,87 @@ def on_search_text_changed(self, text): self.valid_custom_query.emit(True) self.search_state.search() - def on_since_time_changed(self, datetime): - self.since = datetime.toSecsSinceEpoch() + def on_since_time_changed(self, qdatetime): + self.since = qdatetime.toSecsSinceEpoch() + self.search_state.search() + + def on_until_time_changed(self, qdatetime): + self.until = qdatetime.toSecsSinceEpoch() self.search_state.search() - def on_until_time_changed(self, datetime): - self.until = datetime.toSecsSinceEpoch() + def on_select_range(self, set_range): + self.until = time.time() + self.since = self.until-set_range + self.search_state.search() + + def on_select_all(self): + self.until = None + self.since = None self.search_state.search() + + class SearchInputWidget(QWidget): """ Input fields for specifying searches on SearchResultsModel """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.search_bar = QLineEdit() - search_bar_layout = QHBoxLayout() - search_bar_layout.addWidget(QLabel('Custom Query:')) - search_bar_layout.addWidget(self.search_bar) - mongo_query_help_button = QPushButton() - mongo_query_help_button.setText('?') - search_bar_layout.addWidget(mongo_query_help_button) - mongo_query_help_button.clicked.connect(self.show_mongo_query_help) - + # 4 Radiobuttons to quickly select default time period + self.all_widget = QRadioButton("All") + self.days_widget = QRadioButton("30 Days") + self.today_widget = QRadioButton("Today") + self.hour_widget = QRadioButton("Last Hour") + self.radio_button_group = QButtonGroup() + self.radio_button_group.addButton(self.all_widget) + self.radio_button_group.addButton(self.days_widget) + self.radio_button_group.addButton(self.today_widget) + self.radio_button_group.addButton(self.hour_widget) + default_period_layout = QGridLayout() + default_period_layout.addWidget(self.all_widget, 0, 0, 1, 1) + default_period_layout.addWidget(self.days_widget, 0, 1, 1, 1) + default_period_layout.addWidget(self.today_widget, 1, 0, 1, 1) + default_period_layout.addWidget(self.hour_widget, 1, 1, 1, 1) + # Since and Until time selector + self.since_label = QLabel("Since:") self.since_widget = QDateTimeEdit() self.since_widget.setCalendarPopup(True) self.since_widget.setDisplayFormat('yyyy-MM-dd HH:mm') - since_layout = QHBoxLayout() - since_layout.addWidget(QLabel('Since:')) - since_layout.addWidget(self.since_widget) - + self.since_widget.dateTimeChanged.connect(self.uncheck_radiobuttons) + self.until_label = QLabel("Until:") self.until_widget = QDateTimeEdit() self.until_widget.setCalendarPopup(True) self.until_widget.setDisplayFormat('yyyy-MM-dd HH:mm') - until_layout = QHBoxLayout() - until_layout.addWidget(QLabel('Until:')) - until_layout.addWidget(self.until_widget) - - layout = QVBoxLayout() - layout.addLayout(since_layout) - layout.addLayout(until_layout) - layout.addLayout(search_bar_layout) - self.setLayout(layout) + self.until_widget.dateTimeChanged.connect(self.uncheck_radiobuttons) + since_until_layout = QGridLayout() + since_until_layout.addWidget(self.since_label, 0, 0, 1, 1) + since_until_layout.addWidget(self.since_widget, 0, 1, 1, 1) + since_until_layout.addWidget(self.until_label, 1, 0, 1, 1) + since_until_layout.addWidget(self.until_widget, 1, 1, 1, 1) + # Custom Query + self.custom_query_label = QLabel("Custom Query:") + self.search_bar = QLineEdit() + self.mongo_query_help_button = QPushButton("?") + self.mongo_query_help_button.clicked.connect(self.show_mongo_query_help) + search_bar_layout = QHBoxLayout() + search_bar_layout.addWidget(self.custom_query_label) + search_bar_layout.addWidget(self.search_bar) + search_bar_layout.addWidget(self.mongo_query_help_button) + # add individual layouts to search_input_layout + search_input_layout = QVBoxLayout() + search_input_layout.addLayout(default_period_layout) + search_input_layout.addLayout(since_until_layout) + search_input_layout.addLayout(search_bar_layout) + + self.setLayout(search_input_layout) + + def uncheck_radiobuttons(self): + self.radio_button_group.setExclusive(False) + self.all_widget.setChecked(False) + self.days_widget.setChecked(False) + self.today_widget.setChecked(False) + self.hour_widget.setChecked(False) + self.radio_button_group.setExclusive(True) def mark_custom_query(self, valid): "Indicate whether the current text is a parsable query." @@ -478,27 +520,23 @@ def show_mongo_query_help(self): msg.exec_() -class CatalogList(QComboBox): - """ - List of subcatalogs - """ - ... - - class CatalogSelectionWidget(QWidget): """ Input widget for selecting a subcatalog """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.catalog_list = CatalogList() - layout = QHBoxLayout() - layout.addWidget(QLabel("Catalog:")) - layout.addWidget(self.catalog_list) - self.setLayout(layout) + self.catalog = QLabel("Select Catalog:") + self.catalog_list = QComboBox() + horizontal_layout = QHBoxLayout() + horizontal_layout.addWidget(self.catalog) + horizontal_layout.addWidget(self.catalog_list) + self.setLayout(horizontal_layout) + + -class SearchResultsWidget(QTableView): +class SearchResultsWidget(QTableView): """ Table of search results """ diff --git a/xicam/gui/bluesky/summary.py b/xicam/gui/bluesky/summary.py index 53d8300..6a9351c 100644 --- a/xicam/gui/bluesky/summary.py +++ b/xicam/gui/bluesky/summary.py @@ -17,7 +17,7 @@ class SummaryWidget(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.uid_label = QLabel() - self.open_individually_button = QPushButton('Open') + self.open_individually_button = QPushButton('Open Catalog') self.open_individually_button.setEnabled(False) self.open_individually_button.clicked.connect(self._open_individually) self.copy_uid_button = QPushButton('Copy UID to Clipboard')