def pytest_configure(config): os.environ['GLUE_TESTING'] = 'True' if config.getoption('no_optional_skip'): from glue.tests import helpers for attr in helpers.__dict__: if attr.startswith('requires_'): # The following line replaces the decorators with a function # that does noting, effectively disabling it. setattr(helpers, attr, lambda f: f) # Make sure we don't affect the real glue config dir import tempfile from glue import config config.CFG_DIR = tempfile.mkdtemp() # Start up QApplication, if the Qt code is present try: from glue.utils.qt import get_qapp except Exception: # Note that we catch any exception, not just ImportError, because # QtPy can raise a PythonQtError. pass else: get_qapp() # Force loading of plugins from glue.main import load_plugins load_plugins()
def __exit__(self, exc_type, exc_val, tb): if exc_type is None: return # Make sure application has been started from glue.utils.qt import get_qapp # Here to avoid circular import get_qapp() m = "%s\n%s" % (self.msg, exc_val) detail = ''.join(traceback.format_exception(exc_type, exc_val, tb)) if len(m) > 500: detail = "Full message:\n\n%s\n\n%s" % (m, detail) m = m[:500] + '...' from qtpy import QtWidgets from qtpy.QtCore import Qt qmb = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "Error", m) qmb.setDetailedText(detail) qmb.resize(400, qmb.size().height()) qmb.setTextInteractionFlags(Qt.TextSelectableByMouse) qmb.exec_() if self.exit: sys.exit(1) # Just for cases where we are testing and patching sys.exit return True
def new_client(self, dc=None, canvas=None): from glue.utils.qt import get_qapp get_qapp() dc = dc or self.collect l = log.get_logger(name='ginga', log_stderr=True) canvas = ImageViewCanvas(l, render='widget') return GingaClient(dc, canvas)
def pytest_configure(config): if config.getoption('no_optional_skip'): from glue.tests import helpers for attr in helpers.__dict__: if attr.startswith('requires_'): # The following line replaces the decorators with a function # that does noting, effectively disabling it. setattr(helpers, attr, lambda f: f) # Make sure we don't affect the real glue config dir import tempfile from glue import config config.CFG_DIR = tempfile.mkdtemp() # Start up QApplication, if the Qt code is present try: from glue.utils.qt import get_qapp except ImportError: pass else: get_qapp() # Force loading of plugins from glue.main import load_plugins load_plugins()
def new_client(self, dc=None, canvas=None): from glue.utils.qt import get_qapp get_qapp() dc = dc or self.collect l = log.get_logger(name="ginga", log_stderr=True) canvas = ImageViewCanvas(l, render="widget") return GingaClient(dc, canvas)
def test_fit_polynomial(self): # TODO: need to deterministically set to polynomial fitter self.viewer.add_data(self.data) self.profile_tools.ui.tabs.setCurrentIndex(1) # First try in pixel coordinates self.viewer.state.x_att = self.data.pixel_component_ids[0] x, y = self.viewer.axes.transData.transform([[0.9, 4]])[0] self.viewer.axes.figure.canvas.button_press_event(x, y, 1) x, y = self.viewer.axes.transData.transform([[15.1, 4]])[0] self.viewer.axes.figure.canvas.motion_notify_event(x, y, 1) assert_allclose(self.profile_tools.rng_mode.state.x_range, (0.9, 15.1)) self.profile_tools.ui.button_fit.click() self.profile_tools.wait_for_fit() app = get_qapp() app.processEvents() pixel_log = self.profile_tools.text_log.toPlainText().splitlines() assert pixel_log[0] == 'd1' assert pixel_log[1] == 'Coefficients:' assert pixel_log[-2] == '8.000000e+00' assert pixel_log[-1] == '3.500000e+00' self.profile_tools.ui.button_clear.click() assert self.profile_tools.text_log.toPlainText() == '' # Next, try in world coordinates self.viewer.state.x_att = self.data.world_component_ids[0] x, y = self.viewer.axes.transData.transform([[1.9, 4]])[0] self.viewer.axes.figure.canvas.button_press_event(x, y, 1) x, y = self.viewer.axes.transData.transform([[30.1, 4]])[0] self.viewer.axes.figure.canvas.motion_notify_event(x, y, 1) assert_allclose(self.profile_tools.rng_mode.state.x_range, (1.9, 30.1)) self.profile_tools.ui.button_fit.click() self.profile_tools.wait_for_fit() app = get_qapp() app.processEvents() world_log = self.profile_tools.text_log.toPlainText().splitlines() assert world_log[0] == 'd1' assert world_log[1] == 'Coefficients:' assert world_log[-2] == '4.000000e+00' assert world_log[-1] == '3.500000e+00'
def pytest_configure(config): if config.getoption('no_optional_skip'): from glue.tests import helpers for attr in helpers.__dict__: if attr.startswith('requires_'): # The following line replaces the decorators with a function # that does noting, effectively disabling it. setattr(helpers, attr, lambda f: f) # Make sure we don't affect the real glue config dir import tempfile from glue import config config.CFG_DIR = tempfile.mkdtemp() # Start up QApplication, if the Qt code is present try: from glue.utils.qt import get_qapp except ImportError: pass else: app = get_qapp() # Force loading of plugins from glue.main import load_plugins load_plugins()
def wrapper(): from glue.utils.qt import get_qapp app = get_qapp() # Make sure that any window/dialog that needs to be shown is shown app.processEvents() dialog = app.activeWindow() function(dialog)
def __init__(self, layer, parent=None): super(ScatterLayerStyleEditor, self).__init__(parent=parent) self.ui = load_ui('layer_style_editor_scatter.ui', self, directory=os.path.dirname(__file__)) # The following is needed because of a bug in Qt which means that # tab titles don't get scaled right. if platform.system() == 'Darwin': app = get_qapp() app_font = app.font() self.ui.tab_widget.setStyleSheet('font-size: {0}px'.format(app_font.pointSize())) self.layer_state = layer.state self.layer_state.add_callback('xerr_visible', self._update_xerr_att_combo) self.layer_state.add_callback('yerr_visible', self._update_yerr_att_combo) self.layer_state.add_callback('size_mode', self._update_size_mode) self.layer_state.add_callback('cmap_mode', self._update_cmap_mode) self.layer_state.add_callback('layer', self._update_warnings) self._update_xerr_att_combo() self._update_yerr_att_combo() self._update_size_mode() self._update_cmap_mode() self._update_warnings()
def in_process_console(console_class=RichJupyterWidget, **kwargs): """ Create a console widget, connected to an in-process Kernel Keyword arguments will be added to the namespace of the shell. Parameters ---------- console_class : `type` The class of the console widget to create """ global kernel_manager, kernel_client if kernel_manager is None: start_in_process_kernel() app = get_qapp() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() app.exit() control = console_class() control._display_banner = False control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.shell = kernel_manager.kernel.shell control.shell.user_ns.update(**kwargs) control.setWindowTitle('IPython Terminal - type howto() for instructions') return control
def __init__(self, session, parent=None): """ :type session: :class:`~glue.core.Session` """ QtWidgets.QMainWindow.__init__(self, parent) ViewerBase.__init__(self, session) self.setWindowIcon(get_qapp().windowIcon()) self._view = LayerArtistWidget( layer_style_widget_cls=self._layer_style_widget_cls, hub=session.hub) self._view.layer_list.setModel(self._layer_artist_container.model) self._tb_vis = {} # store whether toolbars are enabled self.setAttribute(Qt.WA_DeleteOnClose) self.setAcceptDrops(True) self.setAnimated(False) self.toolbar = None self._toolbars = [] self._warn_close = True self.setContentsMargins(2, 2, 2, 2) self._mdi_wrapper = None # GlueMdiSubWindow that self is embedded in self.statusBar().setStyleSheet("QStatusBar{font-size:10px}") # close window when last plot layer deleted if self._close_on_last_layer_removed: self._layer_artist_container.on_empty( lambda: self.close(warn=False)) self._layer_artist_container.on_changed(self.update_window_title)
def test_navigate_sync_image(self): self.viewer.add_data(self.data) image_viewer = self.app.new_data_viewer(ImageViewer) image_viewer.add_data(self.data) assert image_viewer.state.slices == (0, 0, 0) self.viewer.state.x_att = self.data.pixel_component_ids[0] # Force events to be processed to make sure that the callback functions # for the computation thread are executed (since they rely on signals) self.viewer.layers[0].wait() app = get_qapp() app.processEvents() x, y = self.viewer.axes.transData.transform([[1, 4]])[0] self.viewer.axes.figure.canvas.button_press_event(x, y, 1) self.viewer.axes.figure.canvas.button_release_event(x, y, 1) assert image_viewer.state.slices == (1, 0, 0) self.viewer.state.x_att = self.data.world_component_ids[0] x, y = self.viewer.axes.transData.transform([[10, 4]])[0] self.viewer.axes.figure.canvas.button_press_event(x, y, 1) self.viewer.axes.figure.canvas.button_release_event(x, y, 1) assert image_viewer.state.slices == (5, 0, 0)
def test_same_data(self): # Test that we can't set the same data twice app = get_qapp() dialog = LinkEditor(self.data_collection) dialog.show() link_widget = dialog.link_widget link_widget.state.data1 = self.data1 link_widget.state.data2 = self.data2 assert link_widget.state.data1 == self.data1 assert link_widget.state.data2 == self.data2 link_widget.state.data1 = self.data2 assert link_widget.state.data1 == self.data2 assert link_widget.state.data2 == self.data1 link_widget.state.data2 = self.data2 assert link_widget.state.data1 == self.data1 assert link_widget.state.data2 == self.data2
def __init__(self, layer, parent=None): super(ScatterLayerStyleEditor, self).__init__(parent=parent) self.ui = load_ui('layer_style_editor_scatter.ui', self, directory=os.path.dirname(__file__)) # The following is needed because of a bug in Qt which means that # tab titles don't get scaled right. app = get_qapp() app_font = app.font() self.ui.tab_widget.setStyleSheet('font-size: {0}px'.format(app_font.pointSize())) self.layer_state = layer.state self.layer_state.add_callback('xerr_visible', self._update_xerr_att_combo) self.layer_state.add_callback('yerr_visible', self._update_yerr_att_combo) self.layer_state.add_callback('size_mode', self._update_size_mode) self.layer_state.add_callback('cmap_mode', self._update_cmap_mode) self.layer_state.add_callback('layer', self._update_warnings) self._update_xerr_att_combo() self._update_yerr_att_combo() self._update_size_mode() self._update_cmap_mode() self._update_warnings()
def test_table_widget_session_no_subset(tmpdir): # Regression test for a bug that caused table viewers with no subsets to # not be restored correctly and instead raise an exception. app = get_qapp() # noqa d = Data(a=[1, 2, 3, 4, 5], b=[3.2, 1.2, 4.5, 3.3, 2.2], c=['e', 'b', 'c', 'a', 'f'], label='test') dc = DataCollection([d]) gapp = GlueApplication(dc) widget = gapp.new_data_viewer(TableViewer) widget.add_data(d) session_file = tmpdir.join('table.glu').strpath gapp.save_session(session_file) gapp2 = GlueApplication.restore_session(session_file) gapp2.show() gapp2.data_collection[0] gapp2.viewers[0][0]
def __init__(self, axes, **kwargs): super(RoiMode, self).__init__(axes, **kwargs) self._start_event = None self._drag = False app = get_qapp() self._drag_dist = app.startDragDistance()
def fix_tab_widget_fontsize(tab_widget): """ Because of a bug in Qt, tab titles on MacOS X don't have the right font size """ if platform.system() == 'Darwin': app = get_qapp() app_font = app.font() tab_widget.setStyleSheet('font-size: {0}px'.format(app_font.pointSize()))
def result(*args, **kwargs): from glue.utils.qt import get_qapp # Here to avoid circ import app = get_qapp() app.setOverrideCursor(shape) try: return func(*args, **kwargs) finally: app.restoreOverrideCursor()
def __init__(self, viewer, **kwargs): super(RoiMode, self).__init__(viewer, **kwargs) self._start_event = None self._drag = False app = get_qapp() self._drag_dist = app.startDragDistance()
def wait(self): if QT_INSTALLED: # Wait 0.5 seconds to make sure that the computation has properly started time.sleep(0.5) while self._worker.running: time.sleep(1 / 25) from glue.utils.qt import get_qapp app = get_qapp() app.processEvents()
def set_cursor_cm(shape): """Context manager equivalent for :func:`set_cursor`.""" from glue.utils.qt import get_qapp app = get_qapp() app.setOverrideCursor(shape) try: yield finally: app.restoreOverrideCursor()
def __init__(self, data_collection=None, session=None): # At this point we need to check if a Qt application already exists - # this happens for example if using the %gui qt/qt5 mode in Jupyter. We # should keep a reference to the original icon so that we can restore it # later self._original_app = QtWidgets.QApplication.instance() if self._original_app is not None: self._original_icon = self._original_app.windowIcon() self._export_helper = ExportHelper(self) self._import_helper = ImportHelper(self) # Now we can get the application instance, which involves setting it # up if it doesn't already exist. self.app = get_qapp() QtWidgets.QMainWindow.__init__(self) Application.__init__(self, data_collection=data_collection, session=session) # Pull in any keybindings from an external file self.keybindings = keyboard_shortcut icon = get_icon('app_icon') self.app.setWindowIcon(icon) # Even though we loaded the plugins in start_glue, we re-load them here # in case glue was started directly by initializing this class. load_plugins(require_qt_plugins=True) self.setWindowTitle("Glue") self.setWindowIcon(icon) self.setAttribute(Qt.WA_DeleteOnClose) self._actions = {} self._terminal = None self._setup_ui() self.tab_widget.setMovable(True) self.tab_widget.setTabsClosable(True) # The following is a counter that never goes down, even if tabs are # deleted (this is by design, to avoid having two tabs called the # same if a tab is removed then a new one added again) self._total_tab_count = 0 lwidget = self._layer_widget a = PlotAction(lwidget, self) lwidget.ui.layerTree.addAction(a) self._tweak_geometry() self._create_actions() self._create_menu() self._connect() self.new_tab() self._update_viewer_in_focus()
def main(argv=sys.argv): """ The majority of the code in this function was taken from start_glue() in main.py after a discussion with Tom Robataille. We wanted the ability to get command line arguments and use them in here and this seemed to be the cleanest way to do it. """ # Make sure the mosviz startup item is registered from .startup import mosviz_setup # noqa parser = argparse.ArgumentParser() parser.add_argument('data_files', nargs=argparse.REMAINDER) args = parser.parse_known_args(argv[1:]) import glue from glue.utils.qt import get_qapp app = get_qapp() # Splash screen splash = get_splash() splash.image = QtGui.QPixmap(MOSVIZ_SPLASH_PATH) splash.show() # Start off by loading plugins. We need to do this before restoring # the session or loading the configuration since these may use existing # plugins. load_plugins(splash=splash) datafiles = args[0].data_files # # Show the splash screen for 2 seconds timer = QTimer() timer.setInterval(2000) timer.setSingleShot(True) timer.timeout.connect(splash.close) timer.start() data_collection = glue.core.DataCollection() hub = data_collection.hub splash.set_progress(100) session = glue.core.Session(data_collection=data_collection, hub=hub) ga = GlueApplication(session=session) qapp = QtWidgets.QApplication.instance() ga.setWindowTitle('MOSViz v{0}'.format(__version__)) qapp.setWindowIcon(QtGui.QIcon(MOSVIZ_ICON_PATH)) ga.setWindowIcon(QtGui.QIcon(MOSVIZ_ICON_PATH)) # Load the data files. if datafiles: datasets = load_data_files(datafiles) ga.add_datasets(data_collection, datasets, auto_merge=False) ga.run_startup_action('mosviz') sys.exit(ga.start(maximized=True))
def pytest_configure(config): global app # We need to import PyWWT before setting up a QApplication since the # WebEngine widgets require this. from pywwt.qt import WWTQtClient # noqa from glue.utils.qt import get_qapp app = get_qapp()
def __init__(self, data_collection=None, session=None): # At this point we need to check if a Qt application already exists - # this happens for example if using the %gui qt/qt5 mode in Jupyter. We # should keep a reference to the original icon so that we can restore it # later self._original_app = QtWidgets.QApplication.instance() if self._original_app is not None: self._original_icon = self._original_app.windowIcon() self._export_helper = ExportHelper(self) self._import_helper = ImportHelper(self) # Now we can get the application instance, which involves setting it # up if it doesn't already exist. self.app = get_qapp() QtWidgets.QMainWindow.__init__(self) Application.__init__(self, data_collection=data_collection, session=session) # Pull in any keybindings from an external file self.keybindings = keyboard_shortcut icon = get_icon('app_icon') self.app.setWindowIcon(icon) # Even though we loaded the plugins in start_glue, we re-load them here # in case glue was started directly by initializing this class. load_plugins() self.setWindowTitle("Glue") self.setWindowIcon(icon) self.setAttribute(Qt.WA_DeleteOnClose) self._actions = {} self._terminal = None self._setup_ui() self.tab_widget.setMovable(True) self.tab_widget.setTabsClosable(True) # The following is a counter that never goes down, even if tabs are # deleted (this is by design, to avoid having two tabs called the # same if a tab is removed then a new one added again) self._total_tab_count = 0 lwidget = self._layer_widget a = PlotAction(lwidget, self) lwidget.ui.layerTree.addAction(a) self._tweak_geometry() self._create_actions() self._create_menu() self._connect() self.new_tab() self._update_viewer_in_focus()
def test_aspect_resize(self): # Make sure that the limits are adjusted appropriately when resizing # depending on the aspect ratio mode. Note that we don't add any data # here since it isn't needed for this test. # This test works with Matplotlib 2.0 and 2.2 but not 2.1, hence we # skip it with Matplotlib 2.1 above. app = get_qapp() # Set initial limits to deterministic values self.viewer.state.aspect = 'auto' self.viewer.state.x_min = 0. self.viewer.state.x_max = 1. self.viewer.state.y_min = 0. self.viewer.state.y_max = 1. self.viewer.state.aspect = 'equal' # Resize events only work if widget is visible self.viewer.show() app.processEvents() def limits(viewer): return (viewer.state.x_min, viewer.state.x_max, viewer.state.y_min, viewer.state.y_max) # Set viewer to an initial size and save limits self.viewer.viewer_size = (800, 400) app.processEvents() initial_limits = limits(self.viewer) # Change the viewer size, and make sure the limits are adjusted self.viewer.viewer_size = (400, 400) app.processEvents() with pytest.raises(AssertionError): assert_allclose(limits(self.viewer), initial_limits) # Now change the viewer size a number of times and make sure if we # return to the original size, the limits match the initial ones. self.viewer.viewer_size = (350, 800) app.processEvents() self.viewer.viewer_size = (900, 300) app.processEvents() self.viewer.viewer_size = (600, 600) app.processEvents() self.viewer.viewer_size = (800, 400) app.processEvents() assert_allclose(limits(self.viewer), initial_limits) # Now check that the limits don't change in 'auto' mode self.viewer.state.aspect = 'auto' self.viewer.viewer_size = (900, 300) assert_allclose(limits(self.viewer), initial_limits)
def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: # Make sure application has been started from glue.utils.qt import get_qapp # Here to avoid circ import get_qapp() m = "%s\n%s" % (msg, e) detail = str(traceback.format_exc()) if len(m) > 500: detail = "Full message:\n\n%s\n\n%s" % (m, detail) m = m[:500] + '...' qmb = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "Error", m) qmb.setDetailedText(detail) qmb.show() qmb.raise_() qmb.exec_() sys.exit(1)
def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: # Make sure application has been started from glue.utils.qt import get_qapp # Here to avoid circ import get_qapp() m = "%s\n%s" % (msg, e) detail = str(traceback.format_exc()) if len(m) > 500: detail = "Full message:\n\n%s\n\n%s" % (m, detail) m = m[:500] + '...' qmb = QMessageBox(QMessageBox.Critical, "Error", m) qmb.setDetailedText(detail) qmb.show() qmb.raise_() qmb.exec_() sys.exit(1)
def test_collapse(self): self.viewer.add_data(self.data) image_viewer = self.app.new_data_viewer(ImageViewer) image_viewer.add_data(self.data) self.profile_tools.ui.tabs.setCurrentIndex(2) # First try in pixel coordinates self.viewer.state.x_att = self.data.pixel_component_ids[0] # Force events to be processed to make sure that the callback functions # for the computation thread are executed (since they rely on signals) self.viewer.layers[0].wait() app = get_qapp() app.processEvents() x, y = self.viewer.axes.transData.transform([[0.9, 4]])[0] self.viewer.axes.figure.canvas.button_press_event(x, y, 1) x, y = self.viewer.axes.transData.transform([[15.1, 4]])[0] self.viewer.axes.figure.canvas.motion_notify_event(x, y, 1) self.profile_tools.ui.button_collapse.click() assert isinstance(image_viewer.state.slices[0], AggregateSlice) assert image_viewer.state.slices[0].slice.start == 1 assert image_viewer.state.slices[0].slice.stop == 15 assert image_viewer.state.slices[0].center == 0 assert image_viewer.state.slices[0].function is nanmean # Next, try in world coordinates self.viewer.state.x_att = self.data.world_component_ids[0] # Force events to be processed to make sure that the callback functions # for the computation thread are executed (since they rely on signals) self.viewer.layers[0].wait() app.processEvents() x, y = self.viewer.axes.transData.transform([[1.9, 4]])[0] self.viewer.axes.figure.canvas.button_press_event(x, y, 1) x, y = self.viewer.axes.transData.transform([[30.1, 4]])[0] self.viewer.axes.figure.canvas.motion_notify_event(x, y, 1) self.profile_tools.ui.button_collapse.click() assert isinstance(image_viewer.state.slices[0], AggregateSlice) assert image_viewer.state.slices[0].slice.start == 1 assert image_viewer.state.slices[0].slice.stop == 15 assert image_viewer.state.slices[0].center == 0 assert image_viewer.state.slices[0].function is nanmean
def main(): import numpy as np from glue.utils.qt import get_qapp from glue.core import Data, DataCollection app = get_qapp() x = np.array([1, 2, 3]) d = Data(label='data', x=x, y=x * 2) dc = DataCollection(d) LinkEditor.update_links(dc)
def pytest_configure(config): os.environ['QTWEBENGINE_CHROMIUM_FLAGS'] = '--single-process' global app # We need to import PyWWT before setting up a QApplication since the # WebEngine widgets require this. from pywwt.qt import WWTQtClient # noqa from glue.utils.qt import get_qapp app = get_qapp()
def test_logger_close(): # Regression test to make sure that when closing an application, sys.stderr # no longer points to GlueLogger. app = GlueApplication() app.close() qapp = get_qapp() qapp.processEvents() assert not isinstance(sys.stderr, GlueLogger)
def test_main(): app = get_qapp() w = QMessageBox(QMessageBox.Critical, "Error", "An error occurred") w.setDetailedText("Spam") w.select_all() w.copy_detailed() assert app.clipboard().text() == "Spam" app.quit()
def test_resize(self): # Regression test for a bug that caused images to not be shown at # full resolution after resizing a widget. # This test only runs correctly on Linux on Travis at the moment, # although it works fine locally on MacOS X. I have not yet tracked # down the cause of the failure, but essentially the first time that # self.widget.client._view_window is accessed below, it is still None. # The issue is made more complicated by the fact that whether the test # succeeds or not (after removing code in ImageWidget) depends on # whether another test is run first - in particular I tried with # test_resize from test_application.py. I was able to then get the # test here to pass if the other test_resize was *not* run first. # This should be investigated more in future, but for now, it's most # important that we get the fix in. # What appears to happen when the test fails is that the QTimer gets # started but basically never ends up triggering the timeout. large = core.Data(label='largeim', x=np.random.random((1024, 1024))) self.collect.append(large) app = get_qapp() self.widget.add_data(large) self.widget.show() self.widget.resize(300, 300) time.sleep(0.5) app.processEvents() extx0, exty0 = self.widget.client._view_window[4:] # While resizing, the view window should not change until we've # waited for a bit, to avoid resampling the data every time. for res in range(10): self.widget.resize(300 + res * 30, 300 + res * 30) app.processEvents() extx, exty = self.widget.client._view_window[4:] assert extx == extx0 assert exty == exty0 time.sleep(0.5) app.processEvents() extx, exty = self.widget.client._view_window[4:] assert extx != extx0 assert exty != exty0 self.widget.close()
def activate(self): app = get_qapp() filename, _ = compat.getsavefilename( caption='Save File', basedir='mytour.wtt', filters='WWT Tour File (*.wtt);;', selectedfilter='WWT Tour File (*.wtt);;') # This indicates that the user cancelled if not filename: return if not filename.endswith('.wtt'): filename = filename + '.wtt' self.viewer._wwt.widget.page.runJavaScript("tourxml = '';", asynchronous=False) tourxml = self.viewer._wwt.widget.page.runJavaScript( 'tourxml;', asynchronous=False) self.viewer._wwt.widget.page.runJavaScript(SAVE_TOUR_CODE) start = time.time() tourxml = None while time.time() - start < 10: time.sleep(0.1) app.processEvents() tourxml = self.viewer._wwt.widget.page.runJavaScript( 'tourxml;', asynchronous=False) if tourxml: break if not tourxml: raise Exception("Failed to save tour") # Patch the altUnit so that it is correct for the Windows client (since # the web client currently has other bugs with relation to loading tours). # https://github.com/WorldWideTelescope/wwt-web-client/issues/248 for unit_int in range(1, 11): altunit_str = 'AltUnit="{0}"'.format(unit_int) if altunit_str in tourxml: altunit_str_new = 'AltUnit="{0}"'.format(unit_int - 1) print('Changing {0} to {1} in {2}'.format( altunit_str, altunit_str_new, filename)) tourxml = tourxml.replace(altunit_str, altunit_str_new) with io.open(filename, 'w', newline='') as f: f.write(tourxml)
def setup_method(self, method): self.data1 = Data(x=[1, 2, 3], y=[2, 3, 4], label='data1') self.data2 = Data(a=[1, 2, 3], b=[2, 3, 4], label='data2') self.dc = DataCollection([self.data1, self.data2]) self.x = self.data1.id['x'] self.y = self.data1.id['y'] self.a = self.data2.id['a'] self.b = self.data2.id['b'] self.app = get_qapp() self.dialog = SaveDataDialog(data_collection=self.dc)
def main(): import numpy as np from glue.utils.qt import get_qapp from glue.core import Data, DataCollection app = get_qapp() dc = DataCollection() for i in range(10): x = np.array([1, 2, 3]) d = Data(label='data_{0:02d}'.format(i), x=x, y=x * 2) dc.append(d) LinkEditor.update_links(dc)
def __init__(self, application, parent=None): super(PreferencesDialog, self).__init__(parent=parent) self._app = weakref.ref(application) self.ui = load_ui('preferences.ui', self, directory=os.path.dirname(__file__)) self.ui.cancel.clicked.connect(self.reject) self.ui.ok.clicked.connect(self.accept) self.ui.combo_theme.currentIndexChanged.connect(self._update_colors_from_theme) self.ui.button_reset_dialogs.clicked.connect(self._reset_dialogs) # The following is needed because of a bug in Qt which means that # tab titles don't get scaled right. if platform.system() == 'Darwin': app = get_qapp() app_font = app.font() self.ui.tab_widget.setStyleSheet('font-size: {0}px'.format(app_font.pointSize())) from glue.config import settings self.background = settings.BACKGROUND_COLOR self.foreground = settings.FOREGROUND_COLOR self.data_color = settings.DATA_COLOR self.data_alpha = settings.DATA_ALPHA self.font_size = settings.FONT_SIZE self._update_theme_from_colors() self._autolink_pane = AutolinkPreferencesPane() self.ui.tab_widget.addTab(self._autolink_pane, 'Autolinking') self.panes = [] from glue.config import preference_panes for label, widget_cls in sorted(preference_panes): pane = widget_cls() self.ui.tab_widget.addTab(pane, label) self.panes.append(pane)
def test_change_components(): # Regression test for a bug that caused table viewers to not update when # adding/removing components. For now, this does not work with Qt 5.7. app = get_qapp() # noqa d = Data(a=[1, 2, 3, 4, 5], b=[3.2, 1.2, 4.5, 3.3, 2.2], c=['e', 'b', 'c', 'a', 'f'], label='test') dc = DataCollection([d]) gapp = GlueApplication(dc) viewer = gapp.new_data_viewer(TableViewer) viewer.add_data(d) data_changed = MagicMock() viewer.model.dataChanged.connect(data_changed) # layoutChanged needs to be emitted for the new/removed columns to be # registered (dataChanged is not enough) layout_changed = MagicMock() viewer.model.layoutChanged.connect(layout_changed) assert data_changed.call_count == 0 assert layout_changed.call_count == 0 viewer.model.columnCount() == 2 d.add_component([3, 4, 5, 6, 2], 'z') assert data_changed.call_count == 1 assert layout_changed.call_count == 1 viewer.model.columnCount() == 3 d.remove_component(d.id['z']) assert data_changed.call_count == 2 assert layout_changed.call_count == 2 viewer.model.columnCount() == 2
def __init__(self, data_collection=None, session=None, maximized=True): self.app = get_qapp() QtWidgets.QMainWindow.__init__(self) Application.__init__(self, data_collection=data_collection, session=session) self.app.setQuitOnLastWindowClosed(True) icon = get_icon('app_icon') self.app.setWindowIcon(icon) # Even though we loaded the plugins in start_glue, we re-load them here # in case glue was started directly by initializing this class. load_plugins() self.setWindowTitle("Glue") self.setWindowIcon(icon) self.setAttribute(Qt.WA_DeleteOnClose) self._actions = {} self._terminal = None self._setup_ui() self.tab_widget.setMovable(True) self.tab_widget.setTabsClosable(True) # The following is a counter that never goes down, even if tabs are # deleted (this is by design, to avoid having two tabs called the # same if a tab is removed then a new one added again) self._total_tab_count = 0 lwidget = self._layer_widget a = PlotAction(lwidget, self) lwidget.ui.layerTree.addAction(a) lwidget.bind_selection_to_edit_subset() self._tweak_geometry(maximized=maximized) self._create_actions() self._create_menu() self._connect() self.new_tab() self._update_plot_dashboard(None)
def __init__(self, parent=None): """ :type session: :class:`~glue.core.Session` """ super(BaseQtViewerWidget, self).__init__(parent) self.setWindowIcon(get_qapp().windowIcon()) status_bar = self.statusBar() status_bar.setSizeGripEnabled(False) status_bar.setStyleSheet("QStatusBar{font-size:10px}") self.setFocusPolicy(Qt.StrongFocus) self.setAttribute(Qt.WA_DeleteOnClose) self.setAcceptDrops(True) self.setAnimated(False) self.setContentsMargins(2, 2, 2, 2) self._mdi_wrapper = None # GlueMdiSubWindow that self is embedded in self._warn_close = True
def create_app(datafiles=[], interactive=True): app = get_qapp() if interactive: # Splash screen splash = get_splash() splash.image = QtGui.QPixmap(MOSVIZ_SPLASH_PATH) splash.show() else: splash = None # Start off by loading plugins. We need to do this before restoring # the session or loading the configuration since these may use existing # plugins. load_plugins(splash=splash) # # Show the splash screen for 2 seconds if interactive: timer = QTimer() timer.setInterval(2000) timer.setSingleShot(True) timer.timeout.connect(splash.close) timer.start() data_collection = glue.core.DataCollection() hub = data_collection.hub if interactive: splash.set_progress(100) ga = _create_glue_app(data_collection, hub) ga.run_startup_action('mosviz') # Load the data files. if datafiles: datasets = load_data_files(datafiles) ga.add_datasets(data_collection, datasets, auto_merge=False) return ga
def test_close_on_last_layer_remove(self): # regression test for 391 # Note: processEvents is needed for things to work correctly with PySide2 qtapp = get_qapp() d1 = Data(x=np.random.random((2,) * self.ndim)) d2 = Data(y=np.random.random((2,) * self.ndim)) dc = DataCollection([d1, d2]) app = GlueApplication(dc) w = app.new_data_viewer(self.widget_cls, data=d1) w.add_data(d2) qtapp.processEvents() assert len(app.viewers[0]) == 1 dc.remove(d1) qtapp.processEvents() assert len(app.viewers[0]) == 1 dc.remove(d2) qtapp.processEvents() assert len(app.viewers[0]) == 0 app.close()
def test_table_title(): app = get_qapp() # noqa data1 = Data(a=[1, 2, 3, 4, 5], label='test1') data2 = Data(a=[1, 2, 3, 4, 5], label='test2') dc = DataCollection([data1, data2]) gapp = GlueApplication(dc) viewer = gapp.new_data_viewer(TableViewer) assert viewer.windowTitle() == 'Table' viewer.add_data(data1) assert viewer.windowTitle() == 'Table: test1' viewer.add_data(data2) assert viewer.windowTitle() == 'Table: test2'
def _setup_ctxbar(self): l = self.widget.centralWidget().layout() self._contexts = [NavContext(self), FitContext(self), CollapseContext(self)] tabs = QtWidgets.QTabWidget(parent=self.widget) # The following is needed because of a bug in Qt which means that # tab titles don't get scaled right. if platform.system() == 'Darwin': app = get_qapp() app_font = app.font() tabs.setStyleSheet('font-size: {0}px'.format(app_font.pointSize())) tabs.addTab(self._contexts[0].widget, 'Navigate') tabs.addTab(self._contexts[1].widget, 'Fit') tabs.addTab(self._contexts[2].widget, 'Collapse') self._tabs = tabs self._tabs.setVisible(False) l.addWidget(tabs) l.setStretchFactor(tabs, 0)