Skip to content

Commit

Permalink
Merge pull request #2608 from SasView/2569-whats-new-dialog
Browse files Browse the repository at this point in the history
What's new dialog
  • Loading branch information
Wojciech Potrzebowski authored Sep 18, 2023
2 parents a02cd85 + bed871c commit 26ce41c
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 1 deletion.
1 change: 1 addition & 0 deletions installers/sasview.spec
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ datas = [
('../src/sas/example_data', 'example_data'),
('../src/sas/qtgui/Utilities/Reports/report_style.css', 'sas/qtgui/Utilities/Reports'),
('../src/sas/qtgui/Perspectives/Fitting/plugin_models', 'plugin_models'),
('../src/sas/qtgui/Utilities/WhatsNew/messages', 'sas/qtgui/Utilities/WhatsNew/messages'),
('../src/sas/system/log.ini', 'sas/system/'),
('../../sasmodels/sasmodels','sasmodels'),
('../docs/sphinx-docs/build/html','doc')
Expand Down
11 changes: 10 additions & 1 deletion src/sas/qtgui/MainWindow/GuiManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
from sas.qtgui.Utilities.AddMultEditor import AddMultEditor
from sas.qtgui.Utilities.ImageViewer import ImageViewer
from sas.qtgui.Utilities.FileConverter import FileConverterWidget
from sas.qtgui.Utilities.WhatsNew.WhatsNew import WhatsNew

import sas
from sas import config
Expand Down Expand Up @@ -134,6 +135,9 @@ def __init__(self, parent=None):
"_downloads",
"Tutorial.pdf"))

if self.WhatsNew.has_new_messages():
self.actionWhatsNew()

def info(self, type, value, tb):
logger.error("".join(traceback.format_exception(type, value, tb)))

Expand Down Expand Up @@ -199,6 +203,7 @@ def addWidgets(self):
self.ResolutionCalculator = ResolutionCalculatorPanel(self)
self.DataOperation = DataOperationUtilityPanel(self)
self.FileConverter = FileConverterWidget(self)
self.WhatsNew = WhatsNew(self)

def loadAllPerspectives(self):
# Close any existing perspectives to prevent multiple open instances
Expand Down Expand Up @@ -619,6 +624,9 @@ def actionWelcome(self):
self._workspace.workspace.addSubWindow(self.welcomePanel)
self.welcomePanel.show()

def actionWhatsNew(self):
self.WhatsNew.show()

def showWelcomeMessage(self):
""" Show the Welcome panel, when required """
# Assure the welcome screen is requested
Expand Down Expand Up @@ -734,7 +742,8 @@ def addTriggers(self):
self._workspace.actionAbout.triggered.connect(self.actionAbout)
self._workspace.actionWelcomeWidget.triggered.connect(self.actionWelcome)
self._workspace.actionCheck_for_update.triggered.connect(self.actionCheck_for_update)

self._workspace.actionWhat_s_New.triggered.connect(self.actionWhatsNew)

self.communicate.sendDataToGridSignal.connect(self.showBatchOutput)
self.communicate.resultPlotUpdateSignal.connect(self.showFitResults)

Expand Down
6 changes: 6 additions & 0 deletions src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
<addaction name="actionWelcomeWidget"/>
<addaction name="separator"/>
<addaction name="actionCheck_for_update"/>
<addaction name="actionWhat_s_New"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menuEdit"/>
Expand Down Expand Up @@ -619,6 +620,11 @@
<string>Preferences...</string>
</property>
</action>
<action name="actionWhat_s_New">
<property name="text">
<string>What's New</string>
</property>
</action>
</widget>
<resources/>
<connections/>
Expand Down
5 changes: 5 additions & 0 deletions src/sas/qtgui/MainWindow/UnitTesting/GuiManagerTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@
from sas.qtgui.UnitTesting.TestUtils import QtSignalSpy
from sas.qtgui.Utilities.HidableDialog import HidableDialog

from sas.system import config

class GuiManagerTest:
'''Test the Main Window functionality'''

def __init__(self):
config.override_with_defaults() # Disable saving of test file
config.LAST_WHATS_NEW_HIDDEN_VERSION = "999.999.999" # Give a very large version number

@pytest.fixture(autouse=True)
def manager(self, qapp):
'''Create/Destroy the GUI Manager'''
Expand Down
6 changes: 6 additions & 0 deletions src/sas/qtgui/MainWindow/UnitTesting/MainWindowTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@
from sas.qtgui.Perspectives.Fitting import FittingPerspective
from sas.qtgui.Utilities.HidableDialog import HidableDialog, ShowAgainResult

from sas.system import config
class MainWindowTest:
"""Test the Main Window GUI"""

def __init__(self):
config.override_with_defaults() # Disable saving of test file
config.LAST_WHATS_NEW_HIDDEN_VERSION = "999.999.999" # Give a very large version number

@pytest.fixture(autouse=True)
def widget(self, qapp):
'''Create/Destroy the GUI'''
Expand Down
152 changes: 152 additions & 0 deletions src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
from collections import defaultdict

from PySide6 import QtWidgets
from PySide6.QtWidgets import QDialog, QWidget, QTextBrowser, QVBoxLayout, QHBoxLayout, QPushButton, QCheckBox

from sas.system.version import __version__ as sasview_version
import importlib.resources as resources

from sas.system import config


from sas.qtgui.Utilities.WhatsNew.newer import strictly_newer_than, reduced_version, newest

def whats_new_messages():
""" Accumulate all files that are newer than the value in the config"""

out = defaultdict(list)
message_dir = resources.files("sas.qtgui.Utilities.WhatsNew.messages")
for message_dir in message_dir.iterdir():
# Get short filename
if message_dir.is_dir():

newer = False

try:
newer = strictly_newer_than(message_dir.name, config.LAST_WHATS_NEW_HIDDEN_VERSION)

except ValueError:
pass

if newer:
for file in message_dir.iterdir():
if file.name.endswith(".html"):
out[message_dir.name].append(file)


return out


class WhatsNew(QDialog):
""" What's New window: displays messages about what is new in this version of SasView
It will find all files in messages.[version] if [version] is newer than the last time
the "don't show me again" option was chosen
To add new messages, just dump a (self-contained) html file into the appropriate folder
"""
def __init__(self, parent=None):
super().__init__()

self.setWindowTitle(f"What's New in SasView {sasview_version}")

self.browser = QTextBrowser()

# Layout stuff
self.mainLayout = QVBoxLayout()
self.buttonBar = QWidget()
self.buttonLayout = QHBoxLayout()


# Buttons
self.buttonBar.setLayout(self.buttonLayout)

self.closeButton = QPushButton("Close")
self.nextButton = QPushButton("Next")

self.showAgain = QCheckBox("Show on Startup")
self.showAgain.setChecked(True)

self.buttonLayout.addWidget(self.showAgain)
self.buttonLayout.addWidget(self.closeButton)
self.buttonLayout.addWidget(self.nextButton)

# Viewer
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.browser)
self.mainLayout.addWidget(self.buttonBar)

# Callbacks
self.closeButton.clicked.connect(self.close_me)
self.nextButton.clicked.connect(self.next_file)

# # Gather new files
new_messages = whats_new_messages()
new_message_directories = [key for key in new_messages.keys()]
new_message_directories.sort(key=reduced_version)

self.all_messages = []

for version in new_messages:
self.all_messages += new_messages[version]

self.max_index = len(self.all_messages)
self.current_index = 0

self.show_file()

self.setModal(True)

def next_file(self):
self.current_index += 1
self.current_index %= self.max_index
self.show_file()

def show_file(self):
if len(self.all_messages) > 0:
filename = self.all_messages[self.current_index]
with open(filename, 'r') as fid:
data = fid.read()
self.browser.setText(data)
else:
self.browser.setText("<html><body><h1>You should not see this!!!</h1></body></html>")

def close_me(self):
if not self.showAgain.isChecked():
# We choose the newest, for backwards compatability, i.e. we never reduce the last version
config.LAST_WHATS_NEW_HIDDEN_VERSION = newest(sasview_version, config.LAST_WHATS_NEW_HIDDEN_VERSION)

self.close()

def has_new_messages(self) -> bool:
""" Should the window be shown? """
return bool(self.all_messages)



def maybe_show_whats_new():
global whats_new_window
""" Show the What's New dialogue if it is wanted """

if whats_new_messages():
whats_new_window = WhatsNew()
whats_new_window.show()


def main():
""" Demo/testing window"""

from sas.qtgui.convertUI import main

main()

app = QtWidgets.QApplication([])

maybe_show_whats_new()

app.exec_()


if __name__ == "__main__":
main()
Empty file.
11 changes: 11 additions & 0 deletions src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/1.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>
<head/>
<body>

<h1>
Some Handy Tips
</h1>

Have you tried randomly pressing buttons?
</body>
</html>
10 changes: 10 additions & 0 deletions src/sas/qtgui/Utilities/WhatsNew/messages/6.0.0/2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<html>
<head/>
<body>
<h1>
Welcome to SasView - What's New
</h1>

Lot's of things
</body>
</html>
Empty file.
43 changes: 43 additions & 0 deletions src/sas/qtgui/Utilities/WhatsNew/newer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from typing import Tuple
import re

def reduced_version(version_string: str) -> Tuple[int, int, int]:
""" Convert a version string into the three numbers we care about for the purposes
of the WhatsNew dialog (i.e. strip a,b suffixes etc, make into three ints"""

version_string = re.sub(r"[^\.0-9]+.*", "", version_string)

parts = version_string.split(".")

if len(parts) > 3:
raise ValueError(f"{version_string} not a valid version string")


parts = [int(part) for part in parts]

return tuple(parts + [0]*(3-len(parts)))


def strictly_newer_than(version_a: str, version_b: str) -> bool:
""" Is the version string "version_a" string strictly newer than "version_b" """

numeric_a = reduced_version(version_a)
numeric_b = reduced_version(version_b)

for i in range(3):
if numeric_a[i] > numeric_b[i]:
return True
elif numeric_a[i] < numeric_b[i]:
return False

return False

def newest(version_a: str, version_b: str) -> str:
"""Return the newest of two versions by the comparison used in the what's new box,
if they are equally new, return the first one.
"""

if strictly_newer_than(version_b, version_a):
return version_b

return version_a
3 changes: 3 additions & 0 deletions src/sas/system/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ def __init__(self):
# Default fitting optimizer
self.FITTING_DEFAULT_OPTIMIZER = 'lm'

# What's New variables
self.LAST_WHATS_NEW_HIDDEN_VERSION = "5.0.0"

#
# Lock the class down, this is necessary both for
# securing the class, and for setting up reading/writing files
Expand Down

0 comments on commit 26ce41c

Please sign in to comment.