Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Add an option to mute the confirmation dialog when deleting a dataset #258

Merged
merged 12 commits into from
Feb 6, 2019
7 changes: 3 additions & 4 deletions gwhat/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,15 @@ def __init__(self, parent=None):
self.projectfile = self.whatPref.projectfile
self.projectdir = osp.dirname(self.projectfile)

# Setup the project and data managers :

# Setup the project and data managers.
splash.showMessage("Initializing project and data managers...")
self.pmanager = ProjetManager(self)
self.pmanager.currentProjetChanged.connect(self.new_project_loaded)
self.dmanager = DataManager(parent=self, pm=self.pmanager)
self.dmanager.setMaximumWidth(250)
self.dmanager.sig_new_console_msg.connect(self.write2console)

# Generate the GUI :

# Generate the GUI.
self.__initUI__()
splash.finish(self)
self.showMaximized()
Expand Down
79 changes: 47 additions & 32 deletions gwhat/projet/manager_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
# ---- Third party imports
from PyQt5.QtCore import Qt, QCoreApplication
from PyQt5.QtCore import pyqtSignal as QSignal
from PyQt5.QtWidgets import (QWidget, QComboBox, QGridLayout, QLabel,
QMessageBox, QLineEdit, QPushButton,
QFileDialog, QApplication, QDialog, QGroupBox)
from PyQt5.QtWidgets import (
QWidget, QCheckBox, QComboBox, QGridLayout, QLabel, QMessageBox,
QLineEdit, QPushButton, QFileDialog, QApplication, QDialog, QGroupBox)

# ---- Local library imports
from gwhat.meteo.weather_viewer import WeatherViewer, ExportWeatherButton
Expand All @@ -36,11 +36,13 @@ class DataManager(QWidget):
wldsetChanged = QSignal(object)
wxdsetChanged = QSignal(object)
sig_workdir_changed = QSignal(str)
sig_new_console_msg = QSignal(str)

def __init__(self, parent=None, projet=None, pm=None, pytesting=False):
super(DataManager, self).__init__(parent)
self._pytesting = pytesting
self._projet = projet
self._confirm_before_deleting_dset = True

self.setWindowFlags(Qt.Window)
self.setWindowIcon(icons.get_icon('master'))
Expand Down Expand Up @@ -202,8 +204,28 @@ def emit_warning(self, msg):
btn = QMessageBox.Ok
QMessageBox.warning(self, 'Warning', msg, btn)

# ---- WL Dataset
def confirm_del_dataset(self, dsetname, dsettype):
"""
Show a message box asking the user confirmation before deleting
a dataset. Return the user's answer and whether the
'do not show this message again' checkbox has been checked or not.
"""
msg_box = QMessageBox(
QMessageBox.Question,
"Delete {} dataset '{}'".format(dsettype, dsetname),
("Do you want to delete the {} dataset <i>{}</i>?<br><br>"
"All data will be deleted from the project, but the "
"original data files will be preserved.<br>"
).format(dsettype, dsetname),
buttons=QMessageBox.Yes | QMessageBox.Cancel,
parent=self)
checkbox = QCheckBox("Don't show this message again.")
msg_box.setCheckBox(checkbox)

reply = msg_box.exec_()
return reply, not checkbox.isChecked()

# ---- WL Dataset
@property
def wldsets(self):
"""Return a list of all the wldset saved in the project."""
Expand Down Expand Up @@ -275,25 +297,20 @@ def get_current_wldset(self):
def del_current_wldset(self):
"""Delete the currently selected water level dataset."""
if self.wldsets_cbox.count() > 0:
name = self.wldsets_cbox.currentText()
msg = ('Do you want to delete the dataset <i>%s</i>?'
'<br><br>'
'All data will be deleted from the project database, '
'but the original data files will be preserved') % name
reply = QMessageBox.question(
self, 'Delete current dataset', msg,
QMessageBox.Yes | QMessageBox.No)

if reply == QMessageBox.No:
return

self.projet.del_wldset(name)
dsetname = self.wldsets_cbox.currentText()
if self._confirm_before_deleting_dset:
reply, dont_show_again = self.confirm_del_dataset(
dsetname, 'water level')
if reply == QMessageBox.Cancel:
return
elif reply == QMessageBox.Yes:
self._confirm_before_deleting_dset = dont_show_again
self.projet.del_wldset(dsetname)
self.update_wldsets()
self.update_wldset_info()
self.wldset_changed()

# ---- WX Dataset

@property
def wxdsets(self):
"""Return a list of all the weather datasets saved in the project."""
Expand Down Expand Up @@ -358,20 +375,18 @@ def wxdset_changed(self):
def del_current_wxdset(self):
"""Delete the currently selected weather dataset."""
if self.wxdsets_cbox.count() > 0:
name = self.wxdsets_cbox.currentText()
msg = ('Do you want to delete the weather dataset <i>%s</i>?'
'<br><br>'
'All data will be deleted from the project database, '
'but the original data files will be preserved') % name
reply = QMessageBox.question(
self, 'Delete current dataset', msg,
QMessageBox.Yes | QMessageBox.No)

if reply == QMessageBox.Yes:
self.projet.del_wxdset(name)
self.update_wxdsets()
self.update_wxdset_info()
self.wxdset_changed()
dsetname = self.wxdsets_cbox.currentText()
if self._confirm_before_deleting_dset:
reply, dont_show_again = self.confirm_del_dataset(
dsetname, 'weather')
if reply == QMessageBox.Cancel:
return
elif reply == QMessageBox.Yes:
self._confirm_before_deleting_dset = dont_show_again
self.projet.del_wxdset(dsetname)
self.update_wxdsets()
self.update_wxdset_info()
self.wxdset_changed()

def get_current_wxdset(self):
"""Return the currently selected weather dataset dataframe."""
Expand Down
4 changes: 4 additions & 0 deletions gwhat/projet/reader_projet.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ def add_wldset(self, name, df):
return WLDataFrameHDF5(grp)

def del_wldset(self, name):
"""Delete the specified water level dataset."""
del self.db['wldsets/%s' % name]
self.db.flush()

# ---- Weather Dataset Handlers

Expand Down Expand Up @@ -339,7 +341,9 @@ def add_wxdset(self, name, df):
self.db.flush()

def del_wxdset(self, name):
"""Delete the specified weather dataset."""
del self.db['wxdsets/%s' % name]
self.db.flush()


class WLDataFrameHDF5(dict):
Expand Down
69 changes: 50 additions & 19 deletions gwhat/projet/tests/test_manager_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,21 @@

# ---- Local Libraries Imports
from gwhat.meteo.weather_reader import WXDataFrame
from gwhat.projet.reader_waterlvl import read_water_level_datafile
from gwhat.projet.reader_projet import ProjetReader
from gwhat.projet.manager_data import DataManager, QFileDialog, QMessageBox
from gwhat.projet.manager_data import (DataManager, QFileDialog, QMessageBox,
QCheckBox)

DATADIR = osp.join(osp.dirname(osp.realpath(__file__)), 'data')
WXFILENAME = osp.join(DATADIR, 'sample_weather_datafile.out')
WLFILENAME = osp.join(DATADIR, 'sample_water_level_datafile.csv')


# ---- Pytest Fixtures
@pytest.fixture(scope="module")
def project(tmp_path_factory):
@pytest.fixture
def project(tmpdir):
# Create a project and add add the wldset to it.
basetemp = tmp_path_factory.getbasetemp()
return ProjetReader(osp.join(basetemp, "data_manager_test.gwt"))
return ProjetReader(osp.join(str(tmpdir), "data_manager_test.gwt"))


@pytest.fixture
Expand Down Expand Up @@ -77,18 +78,32 @@ def test_delete_weather_data(datamanager, mocker, qtbot):
"""Test deleting weather datasets from the project."""
datamanager.show()

# Click on the button to delete the weather dataset from the project, but
# answer no.
assert datamanager.wxdataset_count() == 1
mocker.patch.object(QMessageBox, 'question', return_value=QMessageBox.No)
datamanager.new_wxdset_imported('wxdset1', WXDataFrame(WXFILENAME))
datamanager.new_wxdset_imported('wxdset2', WXDataFrame(WXFILENAME))
assert datamanager.wxdataset_count() == 2

# Click to delete the current weather dataset, but cancel.
mock_exec_ = mocker.patch.object(
QMessageBox, 'exec_', return_value=QMessageBox.Cancel)
qtbot.mouseClick(datamanager.btn_del_wxdset, Qt.LeftButton)
assert datamanager.wxdataset_count() == 2
assert datamanager._confirm_before_deleting_dset is True
assert mock_exec_.call_count == 1

# Click to delete the current weather dataset, check the
# 'Don't show this message again' option and answer Yes.
mock_exec_.return_value = QMessageBox.Yes
mocker.patch.object(QCheckBox, 'isChecked', return_value=True)
qtbot.mouseClick(datamanager.btn_del_wxdset, Qt.LeftButton)
assert datamanager.wxdataset_count() == 1
assert datamanager._confirm_before_deleting_dset is False
assert mock_exec_.call_count == 2

# Click on the button to delete the weather dataset from the project and
# answer yes.
mocker.patch.object(QMessageBox, 'question', return_value=QMessageBox.Yes)
# Click to delete the current weather dataset.
qtbot.mouseClick(datamanager.btn_del_wxdset, Qt.LeftButton)
assert datamanager.wxdataset_count() == 0
assert datamanager._confirm_before_deleting_dset is False
assert mock_exec_.call_count == 2


def test_import_waterlevel_data(datamanager, mocker, qtbot):
Expand Down Expand Up @@ -124,18 +139,34 @@ def test_delete_waterlevel_data(datamanager, mocker, qtbot):
"""Test deleting water level datasets from the project."""
datamanager.show()

# Click on the button to delete the water level dataset from the project,
# but answer no.
assert datamanager.wldataset_count() == 1
mocker.patch.object(QMessageBox, 'question', return_value=QMessageBox.No)
datamanager.new_wldset_imported(
'wldset1', read_water_level_datafile(WLFILENAME))
datamanager.new_wldset_imported(
'wldset2', read_water_level_datafile(WLFILENAME))
assert datamanager.wldataset_count() == 2

# Click to delete the current water level dataset, but cancel.
mock_exec_ = mocker.patch.object(
QMessageBox, 'exec_', return_value=QMessageBox.Cancel)
qtbot.mouseClick(datamanager.btn_del_wldset, Qt.LeftButton)
assert datamanager.wldataset_count() == 2
assert datamanager._confirm_before_deleting_dset is True
assert mock_exec_.call_count == 1

# Click to delete the current water level dataset, check the
# 'Don't show this message again' option and answer Yes.
mock_exec_.return_value = QMessageBox.Yes
mocker.patch.object(QCheckBox, 'isChecked', return_value=True)
qtbot.mouseClick(datamanager.btn_del_wldset, Qt.LeftButton)
assert datamanager.wldataset_count() == 1
assert datamanager._confirm_before_deleting_dset is False
assert mock_exec_.call_count == 2

# Click on the button to delete the water level dataset from the project
# and answer yes.
mocker.patch.object(QMessageBox, 'question', return_value=QMessageBox.Yes)
# Click to delete the current weather dataset.
qtbot.mouseClick(datamanager.btn_del_wldset, Qt.LeftButton)
assert datamanager.wldataset_count() == 0
assert datamanager._confirm_before_deleting_dset is False
assert mock_exec_.call_count == 2


# ---- Tests ExportWeatherButton
Expand Down