Skip to content

Commit

Permalink
v1.0.6 features: beefed up UI, cleaner install
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-iris committed Jan 15, 2021
2 parents f50ec04 + 540c3f3 commit 78e6642
Show file tree
Hide file tree
Showing 31 changed files with 1,503 additions and 1,357 deletions.
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[flake8]
ignore = E402
exclude = gui/uic, gui/qrc.py
max-line-length = 110
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
# wingIDE files
*.wpr
*.wpu

# build products
obspy
build
dist
*.app
pyweed.egg-info
16 changes: 5 additions & 11 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
name: pyweed
name: pyweed36
channels:
- conda-forge
- defaults
dependencies:
- python=3.6
- basemap
- future
- basemap=1.3
- matplotlib
- numpy
- obspy=1.1
- pandas
- obspy=1.2.2
- pillow
- pyqt=5.6
- qtconsole
- pyzmq
- pyproj
- proj4=5
- pyqt=5
- proj4
21 changes: 17 additions & 4 deletions installer/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ echo "Looking for Anaconda installation"
export PATH="$PATH:$CONDA_INSTALL_PATH/bin"
hash -r

conda info > /dev/null 2>&1
CONDA_VER=`conda -V` 2>/dev/null
if (( $? )); then
echo "
Anaconda Python not found, do you want to install it? [yes|no]
Expand All @@ -51,10 +51,20 @@ Anaconda Python not found, do you want to install it? [yes|no]

# Useful for debugging any issues with conda
conda info -a

# Update the version
CONDA_VER=`conda -V` 2>/dev/null
else
echo "Found Anaconda at" `conda info --root`
fi

# Environment activation command changed in 4.4
if [[ $CONDA_VER > 'conda 4.4' ]]; then
ACTIVATE_CMD='conda'
else
ACTIVATE_CMD='source'
fi

###
# Create/update the pyweed conda environment

Expand All @@ -80,7 +90,7 @@ Install PyWEED to /Applications folder? [yes|no]
echo "Skipping application bundle"
else
echo "Creating Mac app bundle"
source activate pyweed
$ACTIVATE_CMD activate pyweed
hash -r
pyweed_build_launcher
# Move the old version out of the way if necessary
Expand All @@ -90,15 +100,18 @@ Install PyWEED to /Applications folder? [yes|no]
fi
mv -f $PWD/PyWEED.app /Applications/
echo "Installed to /Applications/PyWEED.app"
# We need to deactivate the environment, or we may get an error
# later when we try to activate it again.
$ACTIVATE_CMD deactivate
fi
fi

###
# User instructions

source activate pyweed
$ACTIVATE_CMD activate pyweed
BIN=`command -v pyweed`
if [[ $BIN != '' ]]; then
if [[ $BIN != '' ]]; then
echo "
You can launch PyWEED from the command line by calling:
Expand Down
2 changes: 1 addition & 1 deletion pyweed/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
__pkg_path___ = os.path.dirname(os.path.abspath(__file__))
# Use Python semantic versioning
# https://packaging.python.org/tutorials/distributing-packages/#semantic-versioning-preferred
__version__ = '1.0.5'
__version__ = '1.0.6'
__app_name__ = "PyWEED"
42 changes: 27 additions & 15 deletions pyweed/gui/ConsoleDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,43 @@
(http://www.gnu.org/copyleft/lesser.html)
"""

from qtconsole.rich_ipython_widget import RichIPythonWidget
from qtconsole.inprocess import QtInProcessKernelManager
from PyQt5 import QtWidgets
from pyweed.gui.BaseDialog import BaseDialog
from logging import getLogger

LOGGER = getLogger(__name__)

class EmbedIPython(RichIPythonWidget):
try:
from qtconsole.rich_ipython_widget import RichIPythonWidget
from qtconsole.inprocess import QtInProcessKernelManager

def __init__(self, **kwarg):
super(RichIPythonWidget, self).__init__()
self.kernel_manager = QtInProcessKernelManager()
self.kernel_manager.start_kernel()
self.kernel = self.kernel_manager.kernel
self.kernel.gui = 'qt4'
self.kernel.shell.push(kwarg)
self.kernel_client = self.kernel_manager.client()
self.kernel_client.start_channels()
class EmbedIPython(RichIPythonWidget):

def __init__(self, **kwarg):
super(RichIPythonWidget, self).__init__()
self.kernel_manager = QtInProcessKernelManager()
self.kernel_manager.start_kernel()
self.kernel = self.kernel_manager.kernel
self.kernel.gui = 'qt4'
self.kernel.shell.push(kwarg)
self.kernel_client = self.kernel_manager.client()
self.kernel_client.start_channels()

except Exception as e:
LOGGER.error("Failed to make IPython widget: %s", e)
EmbedIPython = None


class ConsoleDialog(BaseDialog):
# Enabled if ipython is there
enabled = bool(EmbedIPython)

def __init__(self, pyweed, parent=None):
super(ConsoleDialog, self).__init__(parent=parent)
self.widget = EmbedIPython(pyweed=pyweed)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.widget)
if self.enabled:
self.widget = EmbedIPython(pyweed=pyweed)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.widget)


if __name__ == '__main__':
Expand Down
35 changes: 30 additions & 5 deletions pyweed/gui/MainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ def initialize(self):
# Table selection
self.eventsTable.itemSelectionChanged.connect(self.onEventSelectionChanged)
self.stationsTable.itemSelectionChanged.connect(self.onStationSelectionChanged)
self.allEventSelectionButton.clicked.connect(self.selectAllEvents)
self.clearEventSelectionButton.clicked.connect(self.eventsTable.clearSelection)
self.allStationSelectionButton.clicked.connect(self.selectAllStations)
self.clearStationSelectionButton.clicked.connect(self.stationsTable.clearSelection)

# Main window buttons
Expand All @@ -181,9 +183,18 @@ def initialize(self):
self.getWaveformsButton.clicked.connect(self.getWaveforms)

# Size and placement according to preferences
self.resize(
self.setGeometry(
safe_int(prefs.MainWindow.x, 50),
safe_int(prefs.MainWindow.y, 50),
safe_int(prefs.MainWindow.width, 1000),
safe_int(prefs.MainWindow.height, 800))
safe_int(prefs.MainWindow.height, 800),
)
map_height = safe_int(prefs.MainWindow.mapHeight, 300)
# We can't actually set this for various reasons, it's just a scaled value for the splitter
self.centralSplitter.setSizes([
map_height,
800 - map_height,
])
self.eventOptionsDockWidget.setFloating(safe_bool(prefs.MainWindow.eventOptionsFloat, False))
self.stationOptionsDockWidget.setFloating(safe_bool(prefs.MainWindow.stationOptionsFloat, False))

Expand Down Expand Up @@ -259,11 +270,13 @@ def onMapDrawFinished(self, event):
'longitude': lon,
'maxradius': dist
}
# Set event or station options
# Set event or station options (and ugly event emitter)
if 'events' in event.mode:
self.pyweed.set_event_options(options)
self.eventOptionsWidget.changedCoords.emit(event.mode)
elif 'stations' in event.mode:
self.pyweed.set_station_options(options)
self.stationOptionsWidget.changedCoords.emit(event.mode)

def getEvents(self):
"""
Expand Down Expand Up @@ -479,7 +492,19 @@ def closeEvent(self, event):
def savePreferences(self):
prefs = self.pyweed.preferences

prefs.MainWindow.width = self.width()
prefs.MainWindow.height = self.height()
geometry = self.geometry()
if geometry:
prefs.MainWindow.x = geometry.x()
prefs.MainWindow.y = geometry.y()
prefs.MainWindow.width = geometry.width()
prefs.MainWindow.height = geometry.height()

# We can't actually set the splitter size, just do it as scaled value
splitterSizes = self.centralSplitter.sizes()
if len(splitterSizes) > 1:
prefs.MainWindow.mapHeight = int(
(splitterSizes[0] * 800) / (splitterSizes[0] + splitterSizes[1])
)

prefs.MainWindow.eventOptionsFloat = bool_to_str(self.eventOptionsDockWidget.isFloating())
prefs.MainWindow.stationOptionsFloat = bool_to_str(self.stationOptionsDockWidget.isFloating())
61 changes: 48 additions & 13 deletions pyweed/gui/OptionsWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,34 @@
class BaseOptionsWidget(QtWidgets.QDialog):
"""
Base functionality for the EventOptionsWidget and StationOptionsWidget.
Note that much of this is a (terribly misguided?) attempt to manage the
Qt widget states in a systematic way.
In particular, this attempts to manage an options object held by PyWeedCore,
which is not only Pythonic but has its own peculiar semantics, so we are
translating through like 5 layers of interface here.
"""

# We want to watch for changes in the widget inputs, but every type of input has a different one so
# we need to try a bunch of options
INPUT_CHANGE_SIGNALS = ('valueChanged', 'textChanged', 'dateTimeChanged', 'clicked',)
INPUT_CHANGE_SIGNALS = (
'valueChanged',
'textChanged',
'dateTimeChanged',
'clicked',
'location_choice',
'time_choice',
)

# Signal to indicate that the options have changed
changed = QtCore.pyqtSignal(object)
# Signal indicating that the user changed a location parameter
changedCoords = QtCore.pyqtSignal(object)
# Map of the individual inputs by name
inputs = None
# Flag indicating we are batch updating (ie. don't do per-input events)
updating = False

def __init__(self, parent, options, otherOptions, dockWidget, toggleButton):
super(BaseOptionsWidget, self).__init__(parent=parent)
Expand Down Expand Up @@ -59,8 +75,8 @@ def initialize(self):
self.connectInputs()

# Hook up the shortcut buttons
self.time30DaysPushButton.clicked.connect(self.setTime30Days)
self.time1YearPushButton.clicked.connect(self.setTime1Year)
self.time30DaysToolButton.clicked.connect(self.setTime30Days)
self.time1YearToolButton.clicked.connect(self.setTime1Year)

# Hook up the copy buttons
self.get_timeFromOtherButton().clicked.connect(self.copyTimeOptions)
Expand Down Expand Up @@ -108,14 +124,15 @@ def onInputChanged(self, key):
"""
Called when any input is changed
"""
LOGGER.debug("Input changed: %s" % key)
# Update the core options object
self.options.set_options(self.getOptions())
# Emit a change event
self.changed.emit(key)
# Emit a coordinate change event if appropriate
if self.isCoordinateInput(key):
self.changedCoords.emit(key)
LOGGER.info("Input changed: %s (%s)", key, self.updating)
if not self.updating:
# Update the core options object
self.options.set_options(self.getOptions())
# Emit a change event
self.changed.emit(key)
# Emit a coordinate change event if appropriate
if self.isCoordinateInput(key):
self.changedCoords.emit(key)

def isCoordinateInput(self, key):
"""
Expand Down Expand Up @@ -180,12 +197,18 @@ def setOptions(self):
"""
Put the current set of options into the mapped inputs
"""
# Prevent the individual inputs from signaling a change
self.updating = True
# Get a dictionary of stringified options values
for key, value in self.optionsToInputs(self.options.get_options(stringify=True)).items():
try:
self.setInputValue(key, value)
except Exception as e:
LOGGER.warning("Unable to set input value for %s: %s", key, e)
# Restore signaling
self.updating = False
# Make one signal for the whole update
self.changed.emit('options')

def optionsToInputs(self, values):
"""
Expand Down Expand Up @@ -215,22 +238,34 @@ def copyTimeOptions(self):
"""
Copy the time options from event_options/station_options
"""
LOGGER.info("Copying time to %s" % self.__class__)
LOGGER.info("Copying time")
# Get the options from the other widget
time_options = self.otherOptions.get_time_options()
# Add the radio choice state
time_options.update(self.otherOptions.get_options(['time_choice']))
# Set the options
self.options.set_options(time_options)
# Update the widgets
self.setOptions()
# Send notifications
self.changed.emit('time_choice')

def copyLocationOptions(self):
"""
Copy the location options from event_options/station_options
"""
LOGGER.info("Copying location to %s" % self.__class__)
LOGGER.info("Copying location")
# Get the options from the other widget
loc_options = self.otherOptions.get_location_options()
# Add the radio choice state
loc_options.update(self.otherOptions.get_options(['location_choice']))
# Set the options
self.options.set_options(loc_options)
LOGGER.debug("Settings options: %s", loc_options)
# Update the widgets
self.setOptions()
LOGGER.debug("New options: %s", self.options)
# Send notifications
self.changed.emit('location_choice')
self.changedCoords.emit('location_choice')

Expand Down
Loading

0 comments on commit 78e6642

Please sign in to comment.