コード例 #1
0
 def __init__(self, parent, menu, toolbar):
     QObject.__init__(self, parent)
     self._currier = PersistentCurrier()
     # get list of mouse modes from config
     modelist = []
     for mid in Config.get("mouse-modes", _DefaultModes).split(","):
         if not ConfigFile.has_section(mid):
             print("ERROR: unknown mouse-mode '%s', skipping. Check your %s." % (mid, ConfigFileName))
         else:
             modelist.append(self._readModeConfig(mid))
     self._modes = dict([(mode.id, mode) for mode in modelist])
     self._qag_mode = QActionGroup(self)
     self._qag_submode = QActionGroup(self)
     self._all_submodes = []
     # make entries for main modes
     for mode in modelist:
         mode.addAction(menu, self._qag_mode, callback=self._currier.curry(self._setMode, mode.id))
         if mode.submodes:
             self._all_submodes += list(mode.submodes)
     # make entries for submodes
     self._qa_submode_sep = menu.addSeparator()
     self._modes.update([(mode.id, mode) for mode in self._all_submodes])
     for mode in self._all_submodes:
         mode.addAction(menu, self._qag_submode, toolbar=toolbar,
                        callback=self._currier.curry(self._setSubmode, mode.id))
     # other init
     self._current_context = None
     self._available_submodes = []
     # set initial mode
     initmode = Config.get("current-mouse-mode", _DefaultInitialMode)
     if initmode not in self._modes:
         initmode = modelist[0].id
     self._modes[initmode].qa.setChecked(True)
     self._setMode(initmode, write_config=False)
コード例 #2
0
 def __init__(self, *args):
     TigGUI.kitties.widgets.ClickableTreeWidget.__init__(self, *args)
     self._currier = PersistentCurrier()
     self.model = None
     # insert columns
     self.setHeaderLabels(ViewColumns)
     self.headerItem().setText(ColumnIapp, "I(app)")
     self.header().setMovable(False)
     self.header().setClickable(True)
     self.setSortingEnabled(True)
     self.setRootIsDecorated(False)
     self.setEditTriggers(QAbstractItemView.AllEditTriggers)
     self.setMouseTracking(True)
     # set column width modes
     for icol in range(NumColumns - 1):
         self.header().setResizeMode(icol, QHeaderView.ResizeToContents)
     self.header().setStretchLastSection(True)
     ## self.setTextAlignment(ColumnR,Qt.AlignRight)
     ## self.setTextAlignment(ColumnType,Qt.AlignHCenter)
     # _column_enabled[i] is True if column is available in the model.
     # _column_show[i] is True if column is currently being shown (via a view control)
     self._column_enabled = [True] * NumColumns
     self._column_shown = [True] * NumColumns
     # other listview init
     self.header().show()
     self.setSelectionMode(QTreeWidget.ExtendedSelection)
     self.setAllColumnsShowFocus(True)
     ## self.setShowToolTips(True)
     self._updating_selection = False
     self.setRootIsDecorated(False)
     # connect signals to track selected sources
     QObject.connect(self, SIGNAL("itemSelectionChanged()"),
                     self._selectionChanged)
     QObject.connect(self, SIGNAL("itemEntered(QTreeWidgetItem*,int)"),
                     self._itemHighlighted)
     # add "View" controls for different column categories
     self._column_views = []
     self._column_widths = {}
     self.addColumnCategory("Position", [ColumnRa, ColumnDec])
     self.addColumnCategory("Position errors",
                            [ColumnRa_err, ColumnDec_err], False)
     self.addColumnCategory("Type", [ColumnType])
     self.addColumnCategory("Flux", [ColumnIapp, ColumnI])
     self.addColumnCategory("Flux errors", [ColumnI_err], False)
     self.addColumnCategory("Polarization",
                            [ColumnQ, ColumnU, ColumnV, ColumnRm])
     self.addColumnCategory(
         "Polarization errors",
         [ColumnQ_err, ColumnU_err, ColumnV_err, ColumnRm_err], False)
     self.addColumnCategory("Spectrum", [ColumnSpi])
     self.addColumnCategory("Spectrum errors", [ColumnSpi_err], False)
     self.addColumnCategory("Shape", [ColumnShape])
     self.addColumnCategory("Shape errors", [ColumnShape_err], False)
     self.addColumnCategory("Tags", [ColumnTags])
コード例 #3
0
 def __init__(self, parent, *args):
     QWidget.__init__(self, parent, *args)
     self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
     lo = QVBoxLayout(self)
     lo.setContentsMargins(0, 0, 0, 0)
     lo1 = QHBoxLayout()
     lo.addLayout(lo1)
     lo1.setContentsMargins(0, 0, 0, 0)
     lbl = QLabel(QString("<nobr><b>Source groupings:</b></nobr>"), self)
     lo1.addWidget(lbl, 0)
     lo1.addStretch(1)
     # add show/hide button
     self._showattrbtn = QPushButton(self)
     self._showattrbtn.setMinimumWidth(256)
     lo1.addWidget(self._showattrbtn, 0)
     lo1.addStretch()
     QObject.connect(self._showattrbtn, SIGNAL("clicked()"),
                     self._togglePlotControlsVisibility)
     # add table
     self.table = QTableWidget(self)
     lo.addWidget(self.table)
     QObject.connect(self.table, SIGNAL("cellChanged(int,int)"),
                     self._valueChanged)
     self.table.setSelectionMode(QTableWidget.NoSelection)
     # setup basic columns
     self.table.setColumnCount(6 + len(self.EditableAttrs))
     for i, label in enumerate(
         ("grouping", "total", "selection", "list", "plot", "style")):
         self.table.setHorizontalHeaderItem(i, QTableWidgetItem(label))
     self.table.horizontalHeader().setSectionHidden(self.ColApply, True)
     # setup columns for editable grouping attributes
     for i, attr in self.AttrByCol.items():
         self.table.setHorizontalHeaderItem(
             i, QTableWidgetItem(PlotStyles.StyleAttributeLabels[attr]))
         self.table.horizontalHeader().setSectionHidden(i, True)
     self.table.verticalHeader().hide()
     # other internal init
     self._attrs_shown = False
     self._togglePlotControlsVisibility()
     self.model = None
     self._setting_model = False
     self._currier = PersistentCurrier()
     # row of 'selected' grouping
     self._irow_selgroup = 0
コード例 #4
0
ファイル: Manager.py プロジェクト: razman786/tigger
    def __init__(self, *args):
        QWidget.__init__(self, *args)
        self.mainwin = None
        # init layout
        self._lo = QVBoxLayout(self)
        self._lo.setContentsMargins(0, 0, 0, 0)
        self._lo.setSpacing(0)
        # init internal state
        self._currier = PersistentCurrier()
        self._z0 = 0  # z-depth of first image, the rest count down from it
        self._updating_imap = False
        self._locked_display_range = False
        self._imagecons = []
        self._imagecon_loadorder = []
        self._center_image = None
        self._plot = None
        self._border_pen = None
        self._drawing_key = None
        self._load_image_dialog = None
        self._label_color = None
        self._label_bg_brush = None
        self._model_imagecons = set()
        # init menu and standard actions
        self._menu = QMenu("&Image", self)
        qag = QActionGroup(self)
        # exclusive controls for plotting topmost or all images
        self._qa_plot_top = qag.addAction("Display topmost image only")
        self._qa_plot_all = qag.addAction("Display all images")
        self._qa_plot_top.setCheckable(True)
        self._qa_plot_all.setCheckable(True)
        self._qa_plot_top.setChecked(True)
        self._qa_plot_all.toggled[bool].connect(self._displayAllImages)
        self._closing = False

        self._qa_load_clipboard = None
        self._clipboard_mode = QClipboard.Clipboard
        QApplication.clipboard().changed[QClipboard.Mode].connect(
            self._checkClipboardPath)
        # populate the menu
        self._repopulateMenu()
        self.signalShowMessage = None
        self.signalShowErrorMessage = None
コード例 #5
0
 def __init__(self, image, parent, imgman, name=None, save=False):
     QFrame.__init__(self, parent)
     self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
     # init state
     self._border_pen = None
     self._image_label_text = None
     self._subset = None
     self.image = image
     self._imgman = imgman
     self._currier = PersistentCurrier()
     self._control_dialog = None
     # create widgets
     self._lo = lo = QHBoxLayout(self)
     lo.setContentsMargins(0, 0, 0, 0)
     lo.setSpacing(2)
     # raise button
     self._wraise = QToolButton(self)
     lo.addWidget(self._wraise)
     self._wraise.setIcon(pixmaps.raise_up.icon())
     self._wraise.setAutoRaise(True)
     self._can_raise = False
     self._wraise.clicked.connect(self._raiseButtonPressed)
     self._wraise.setToolTip(
         """<P>Click here to raise this image above other images. Hold the button down briefly to
   show a menu of image operations.</P>""")
     # center label
     self._wcenter = QLabel(self)
     self._wcenter.setPixmap(pixmaps.center_image.pm())
     self._wcenter.setToolTip(
         "<P>The plot is currently centered on (the reference pixel %d,%d) of this image.</P>"
         % self.image.referencePixel())
     lo.addWidget(self._wcenter)
     # name/filename label
     self.name = image.name
     self._wlabel = QLabel(self.name, self)
     self._number = 0
     self.setName(self.name)
     self._wlabel.setToolTip(
         "%s %s" %
         (image.filename, "\u00D7".join(map(str,
                                            image.data().shape))))
     lo.addWidget(self._wlabel, 1)
     # if 'save' is specified, create a "save" button
     if save:
         self._wsave = QToolButton(self)
         lo.addWidget(self._wsave)
         self._wsave.setText("save")
         self._wsave.setAutoRaise(True)
         self._save_dir = save if isinstance(save, str) else "."
         self._wsave.clicked.connect(self._saveImage)
         self._wsave.setToolTip(
             """<P>Click here to write this image to a FITS file.</P>""")
     # render control
     self.image.connectRepaint(self.imageSignalRepaint)
     self.image.connectSlice(self.imageSignalSlice)
     self.image.connectRaise(self.imageSignalRaise)
     self.image.connectUnload(self.imageSignalUnload)
     self.image.connectCenter(self.imageSignalCenter)
     dprint(2, "creating RenderControl")
     self._rc = RenderControl(image, self)
     dprint(2, "done")
     # selectors for extra axes
     self._wslicers = []
     curslice = self._rc.currentSlice(
     )  # this may be loaded from config, so not necessarily 0
     for iextra, axisname, labels in self._rc.slicedAxes():
         if axisname.upper() not in ["STOKES", "COMPLEX"]:
             lbl = QLabel("%s:" % axisname, self)
             lo.addWidget(lbl)
         else:
             lbl = None
         slicer = QComboBox(self)
         self._wslicers.append(slicer)
         lo.addWidget(slicer)
         slicer.addItems(labels)
         slicer.setToolTip(
             """<P>Selects current slice along the %s axis.</P>""" %
             axisname)
         slicer.setCurrentIndex(curslice[iextra])
         slicer.activated[int].connect(
             self._currier.curry(self._rc.changeSlice, iextra))
     # min/max display ranges
     lo.addSpacing(5)
     self._wrangelbl = QLabel(self)
     lo.addWidget(self._wrangelbl)
     self._minmaxvalidator = FloatValidator(self)
     self._wmin = QLineEdit(self)
     self._wmax = QLineEdit(self)
     width = self._wmin.fontMetrics().width("1.234567e-05")
     for w in self._wmin, self._wmax:
         lo.addWidget(w, 0)
         w.setValidator(self._minmaxvalidator)
         w.setMaximumWidth(width)
         w.setMinimumWidth(width)
         w.editingFinished.connect(self._changeDisplayRange)
     # full-range button
     self._wfullrange = QToolButton(self)
     lo.addWidget(self._wfullrange, 0)
     self._wfullrange.setIcon(pixmaps.zoom_range.icon())
     self._wfullrange.setAutoRaise(True)
     self._wfullrange.clicked.connect(
         self.renderControl().resetSubsetDisplayRange)
     rangemenu = QMenu(self)
     rangemenu.addAction(pixmaps.full_range.icon(), "Full subset",
                         self.renderControl().resetSubsetDisplayRange)
     for percent in (99.99, 99.9, 99.5, 99, 98, 95):
         rangemenu.addAction(
             "%g%%" % percent,
             self._currier.curry(self._changeDisplayRangeToPercent,
                                 percent))
     self._wfullrange.setPopupMode(QToolButton.DelayedPopup)
     self._wfullrange.setMenu(rangemenu)
     # update widgets from current display range
     self._updateDisplayRange(*self._rc.displayRange())
     # lock button
     self._wlock = QToolButton(self)
     self._wlock.setIcon(pixmaps.unlocked.icon())
     self._wlock.setAutoRaise(True)
     self._wlock.setToolTip(
         """<P>Click to lock or unlock the intensity range. When the intensity range is locked across multiple images, any changes in the intensity
       range of one are propagated to the others. Hold the button down briefly for additional options.</P>"""
     )
     lo.addWidget(self._wlock)
     self._wlock.clicked.connect(self._toggleDisplayRangeLock)
     self.renderControl().displayRangeLocked.connect(
         self._setDisplayRangeLock)
     self.renderControl().dataSubsetChanged.connect(self._dataSubsetChanged)
     lockmenu = QMenu(self)
     lockmenu.addAction(
         pixmaps.locked.icon(), "Lock all to this",
         self._currier.curry(imgman.lockAllDisplayRanges,
                             self.renderControl()))
     lockmenu.addAction(pixmaps.unlocked.icon(), "Unlock all",
                        imgman.unlockAllDisplayRanges)
     self._wlock.setPopupMode(QToolButton.DelayedPopup)
     self._wlock.setMenu(lockmenu)
     self._setDisplayRangeLock(self.renderControl().isDisplayRangeLocked())
     # dialog button
     self._wshowdialog = QToolButton(self)
     lo.addWidget(self._wshowdialog)
     self._wshowdialog.setIcon(pixmaps.colours.icon())
     self._wshowdialog.setAutoRaise(True)
     self._wshowdialog.setToolTip(
         """<P>Click for colourmap and intensity policy options.</P>""")
     self._wshowdialog.clicked.connect(self.showRenderControls)
     tooltip = """<P>You can change the currently displayed intensity range by entering low and high limits here.</P>
         <TABLE>
         <TR><TD><NOBR>Image min:</NOBR></TD><TD>%g</TD><TD>max:</TD><TD>%g</TD></TR>
         </TABLE>""" % self.image.imageMinMax()
     for w in self._wmin, self._wmax, self._wrangelbl:
         w.setToolTip(tooltip)
     # create image operations menu
     self._menu = QMenu(self.name, self)
     self._qa_raise = self._menu.addAction(
         pixmaps.raise_up.icon(), "Raise image",
         self._currier.curry(self.image.signalRaise.emit, None))
     self._qa_center = self._menu.addAction(
         pixmaps.center_image.icon(), "Center plot on image",
         self._currier.curry(self.image.signalCenter.emit, True))
     self._qa_show_rc = self._menu.addAction(pixmaps.colours.icon(),
                                             "Colours && Intensities...",
                                             self.showRenderControls)
     if save:
         self._qa_save = self._menu.addAction("Save image...",
                                              self._saveImage)
     self._menu.addAction("Export image to PNG file...",
                          self._exportImageToPNG)
     self._export_png_dialog = None
     self._menu.addAction(
         "Unload image",
         self._currier.curry(self.image.signalUnload.emit, None))
     self._wraise.setMenu(self._menu)
     self._wraise.setPopupMode(QToolButton.DelayedPopup)
     # connect updates from renderControl and image
     self.image.signalSlice.connect(self._updateImageSlice)
     self._rc.displayRangeChanged.connect(self._updateDisplayRange)
     # default plot depth of image markers
     self._z_markers = None
     # and the markers themselves
     self._image_border = QwtPlotCurve()
     self._image_border.setRenderHint(QwtPlotItem.RenderAntialiased)
     self._image_label = QwtPlotMarker()
     self._image_label.setRenderHint(QwtPlotItem.RenderAntialiased)
     # subset markers
     self._subset_pen = QPen(QColor("Light Blue"))
     self._subset_border = QwtPlotCurve()
     self._subset_border.setRenderHint(QwtPlotItem.RenderAntialiased)
     self._subset_border.setPen(self._subset_pen)
     self._subset_border.setVisible(False)
     self._subset_label = QwtPlotMarker()
     self._subset_label.setRenderHint(QwtPlotItem.RenderAntialiased)
     text = QwtText("subset")
     text.setColor(self._subset_pen.color())
     self._subset_label.setLabel(text)
     self._subset_label.setLabelAlignment(Qt.AlignRight | Qt.AlignBottom)
     self._subset_label.setVisible(False)
     self._setting_lmrect = False
     self._all_markers = [
         self._image_border, self._image_label, self._subset_border,
         self._subset_label
     ]
     self._exportMaxRes = False
     self._dockable_colour_ctrl = None
コード例 #6
0
    def __init__(self, parent, rc, imgman):
        """An ImageControlDialog is initialized with a parent widget, a RenderControl object,
        and an ImageManager object"""
        QDialog.__init__(self, parent)
        image = rc.image
        self.setWindowTitle("%s: Colour Controls" % image.name)
        self.setWindowIcon(pixmaps.colours.icon())
        self.setModal(False)
        self.image = image
        self._rc = rc
        self._imgman = imgman
        self._currier = PersistentCurrier()

        # init internal state
        self._prev_range = self._display_range = None, None
        self._hist = None
        self._geometry = None

        # create layouts
        lo0 = QVBoxLayout(self)
        #    lo0.setContentsMargins(0,0,0,0)

        # histogram plot
        whide = self.makeButton("Hide", self.hide, width=128)
        whide.setShortcut(Qt.Key_F9)
        lo0.addWidget(Separator(self, "Histogram and ITF", extra_widgets=[whide]))
        lo1 = QHBoxLayout()
        lo1.setContentsMargins(0, 0, 0, 0)
        self._histplot = QwtPlot(self)
        self._histplot.setAutoDelete(False)
        lo1.addWidget(self._histplot, 1)
        lo2 = QHBoxLayout()
        lo2.setContentsMargins(0, 0, 0, 0)
        lo2.setSpacing(2)
        lo0.addLayout(lo2)
        lo0.addLayout(lo1)
        self._wautozoom = QCheckBox("autozoom", self)
        self._wautozoom.setChecked(True)
        self._wautozoom.setToolTip("""<P>If checked, then the histrogram plot will zoom in automatically when
      you narrow the current intensity range.</P>""")
        self._wlogy = QCheckBox("log Y", self)
        self._wlogy.setChecked(True)
        self._ylogscale = True
        self._wlogy.setToolTip(
            """<P>If checked, a log-scale Y axis is used for the histogram plot instead of a linear one.""")
        QObject.connect(self._wlogy, SIGNAL("toggled(bool)"), self._setHistLogScale)
        self._whistunzoom = self.makeButton("", self._unzoomHistogram, icon=pixmaps.full_range.icon())
        self._whistzoomout = self.makeButton("-", self._currier.curry(self._zoomHistogramByFactor, math.sqrt(.1)))
        self._whistzoomin = self.makeButton("+", self._currier.curry(self._zoomHistogramByFactor, math.sqrt(10)))
        self._whistzoomin.setToolTip("""<P>Click to zoom into the histogram plot by one step. This does not
      change the current intensity range.</P>""")
        self._whistzoomout.setToolTip("""<P>Click to zoom out of the histogram plot by one step. This does not
      change the current intensity range.</P>""")
        self._whistunzoom.setToolTip("""<P>Click to reset the histogram plot back to its full extent.
      This does not change the current intensity range.</P>""")
        self._whistzoom = QwtWheel(self)
        self._whistzoom.setOrientation(Qt.Horizontal)
        self._whistzoom.setMaximumWidth(80)
        self._whistzoom.setRange(10, 0)
        self._whistzoom.setStep(0.1)
        self._whistzoom.setTickCnt(30)
        self._whistzoom.setTracking(False)
        QObject.connect(self._whistzoom, SIGNAL("valueChanged(double)"), self._zoomHistogramFinalize)
        QObject.connect(self._whistzoom, SIGNAL("sliderMoved(double)"), self._zoomHistogramPreview)
        self._whistzoom.setToolTip("""<P>Use this wheel control to zoom in/out of the histogram plot.
      This does not change the current intensity range.
      Note that the zoom wheel should also respond to your mouse wheel, if you have one.</P>""")
        # This works around a stupid bug in QwtSliders -- when using the mousewheel, only sliderMoved() signals are emitted,
        # with no final  valueChanged(). If we want to do a fast preview of something on sliderMoved(), and a "slow" final
        # step on valueChanged(), we're in trouble. So we start a timer on sliderMoved(), and if the timer expires without
        # anything else happening, do a valueChanged().
        # Here we use a timer to call zoomHistogramFinalize() w/o an argument.
        self._whistzoom_timer = QTimer(self)
        self._whistzoom_timer.setSingleShot(True)
        self._whistzoom_timer.setInterval(500)
        QObject.connect(self._whistzoom_timer, SIGNAL("timeout()"), self._zoomHistogramFinalize)
        # set same size for all buttons and controls
        width = 24
        for w in self._whistunzoom, self._whistzoomin, self._whistzoomout:
            w.setMinimumSize(width, width)
            w.setMaximumSize(width, width)
        self._whistzoom.setMinimumSize(80, width)
        self._wlab_histpos_text = "(hover here for help)"
        self._wlab_histpos = QLabel(self._wlab_histpos_text, self)
        self._wlab_histpos.setToolTip("""
      <P>The plot shows a histogram of either the full image or its selected subset
      (as per the "Data subset" section below).</P>
      <P>The current intensity range is indicated by the grey box
      in the plot.</P>
      <P>Use the left mouse button to change the low intensity limit, and the right
      button (on Macs, use Ctrl-click) to change the high limit.</P>
      <P>Use Shift with the left mouse button to zoom into an area of the histogram,
      or else use the "zoom wheel" control or the plus/minus toolbuttons above the histogram to zoom in or out.
      To zoom back out to the full extent of the histogram, click on the rightmost button above the histogram.</P>
      """)
        lo2.addWidget(self._wlab_histpos, 1)
        lo2.addWidget(self._wautozoom)
        lo2.addWidget(self._wlogy, 0)
        lo2.addWidget(self._whistzoomin, 0)
        lo2.addWidget(self._whistzoom, 0)
        lo2.addWidget(self._whistzoomout, 0)
        lo2.addWidget(self._whistunzoom, 0)
        self._zooming_histogram = False

        sliced_axes = rc.slicedAxes()
        dprint(1, "sliced axes are", sliced_axes)
        self._stokes_axis = None

        # subset indication
        lo0.addWidget(Separator(self, "Data subset"))
        # sliced axis selectors
        self._wslicers = []
        if sliced_axes:
            lo1 = QHBoxLayout()
            lo1.setContentsMargins(0, 0, 0, 0)
            lo1.setSpacing(2)
            lo0.addLayout(lo1)
            lo1.addWidget(QLabel("Current slice:  ", self))
            for i, (iextra, name, labels) in enumerate(sliced_axes):
                lo1.addWidget(QLabel("%s:" % name, self))
                if name == "STOKES":
                    self._stokes_axis = iextra
                # add controls
                wslicer = QComboBox(self)
                self._wslicers.append(wslicer)
                wslicer.addItems(labels)
                wslicer.setToolTip("""<P>Selects current slice along the %s axis.</P>""" % name)
                wslicer.setCurrentIndex(self._rc.currentSlice()[iextra])
                QObject.connect(wslicer, SIGNAL("activated(int)"), self._currier.curry(self._rc.changeSlice, iextra))
                lo2 = QVBoxLayout()
                lo1.addLayout(lo2)
                lo2.setContentsMargins(0, 0, 0, 0)
                lo2.setSpacing(0)
                wminus = QToolButton(self)
                wminus.setArrowType(Qt.UpArrow)
                QObject.connect(wminus, SIGNAL("clicked()"), self._currier.curry(self._rc.incrementSlice, iextra, 1))
                if i == 0:
                    wminus.setShortcut(Qt.SHIFT + Qt.Key_F7)
                elif i == 1:
                    wminus.setShortcut(Qt.SHIFT + Qt.Key_F8)
                wplus = QToolButton(self)
                wplus.setArrowType(Qt.DownArrow)
                QObject.connect(wplus, SIGNAL("clicked()"), self._currier.curry(self._rc.incrementSlice, iextra, -1))
                if i == 0:
                    wplus.setShortcut(Qt.Key_F7)
                elif i == 1:
                    wplus.setShortcut(Qt.Key_F8)
                wminus.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
                wplus.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
                sz = QSize(12, 8)
                wminus.setMinimumSize(sz)
                wplus.setMinimumSize(sz)
                wminus.resize(sz)
                wplus.resize(sz)
                lo2.addWidget(wminus)
                lo2.addWidget(wplus)
                lo1.addWidget(wslicer)
                lo1.addSpacing(5)
            lo1.addStretch(1)
        # subset indicator
        lo1 = QHBoxLayout()
        lo1.setContentsMargins(0, 0, 0, 0)
        lo1.setSpacing(2)
        lo0.addLayout(lo1)
        self._wlab_subset = QLabel("Subset: xxx", self)
        self._wlab_subset.setToolTip("""<P>This indicates the current data subset to which the histogram
      and the stats given here apply. Use the "Reset to" control on the right to change the
      current subset and recompute the histogram and stats.</P>""")
        lo1.addWidget(self._wlab_subset, 1)

        self._wreset_full = self.makeButton("\u2192 full", self._rc.setFullSubset)
        lo1.addWidget(self._wreset_full)
        if sliced_axes:
            #      if self._stokes_axis is not None and len(sliced_axes)>1:
            #        self._wreset_stokes = self.makeButton(u"\u21920Stokes",self._rc.setFullSubset)
            self._wreset_slice = self.makeButton("\u2192 slice", self._rc.setSliceSubset)
            lo1.addWidget(self._wreset_slice)
        else:
            self._wreset_slice = None

        # min/max controls
        lo1 = QHBoxLayout()
        lo1.setContentsMargins(0, 0, 0, 0)
        lo0.addLayout(lo1, 0)
        self._wlab_stats = QLabel(self)
        lo1.addWidget(self._wlab_stats, 0)
        self._wmore_stats = self.makeButton("more...", self._showMeanStd)
        self._wlab_stats.setMinimumHeight(self._wmore_stats.height())
        lo1.addWidget(self._wmore_stats, 0)
        lo1.addStretch(1)

        # intensity controls
        lo0.addWidget(Separator(self, "Intensity mapping"))
        lo1 = QHBoxLayout()
        lo1.setContentsMargins(0, 0, 0, 0)
        lo1.setSpacing(2)
        lo0.addLayout(lo1, 0)
        self._range_validator = FloatValidator(self)
        self._wrange = QLineEdit(self), QLineEdit(self)
        self._wrange[0].setToolTip("""<P>This is the low end of the intensity range.</P>""")
        self._wrange[1].setToolTip("""<P>This is the high end of the intensity range.</P>""")
        for w in self._wrange:
            w.setValidator(self._range_validator)
            QObject.connect(w, SIGNAL("editingFinished()"), self._changeDisplayRange)
        lo1.addWidget(QLabel("low:", self), 0)
        lo1.addWidget(self._wrange[0], 1)
        self._wrangeleft0 = self.makeButton("\u21920", self._setZeroLeftLimit, width=32)
        self._wrangeleft0.setToolTip("""<P>Click this to set the low end of the intensity range to 0.</P>""")
        lo1.addWidget(self._wrangeleft0, 0)
        lo1.addSpacing(8)
        lo1.addWidget(QLabel("high:", self), 0)
        lo1.addWidget(self._wrange[1], 1)
        lo1.addSpacing(8)
        self._wrange_full = self.makeButton(None, self._setHistDisplayRange, icon=pixmaps.intensity_graph.icon())
        lo1.addWidget(self._wrange_full)
        self._wrange_full.setToolTip(
            """<P>Click this to reset the intensity range to the current extent of the histogram plot.</P>""")
        # add menu for display range
        range_menu = QMenu(self)
        wrange_menu = QToolButton(self)
        wrange_menu.setText("Reset to")
        wrange_menu.setToolTip("""<P>Use this to reset the intensity range to various pre-defined settings.</P>""")
        lo1.addWidget(wrange_menu)
        self._qa_range_full = range_menu.addAction(pixmaps.full_range.icon(), "Full subset",
                                                   self._rc.resetSubsetDisplayRange)
        self._qa_range_hist = range_menu.addAction(pixmaps.intensity_graph.icon(), "Current histogram limits",
                                                   self._setHistDisplayRange)
        for percent in (99.99, 99.9, 99.5, 99, 98, 95):
            range_menu.addAction("%g%%" % percent, self._currier.curry(self._changeDisplayRangeToPercent, percent))
        wrange_menu.setMenu(range_menu)
        wrange_menu.setPopupMode(QToolButton.InstantPopup)

        lo1 = QGridLayout()
        lo1.setContentsMargins(0, 0, 0, 0)
        lo0.addLayout(lo1, 0)
        self._wimap = QComboBox(self)
        lo1.addWidget(QLabel("Intensity policy:", self), 0, 0)
        lo1.addWidget(self._wimap, 1, 0)
        self._wimap.addItems(rc.getIntensityMapNames())
        QObject.connect(self._wimap, SIGNAL("currentIndexChanged(int)"), self._rc.setIntensityMapNumber)
        self._wimap.setToolTip("""<P>Use this to change the type of the intensity transfer function (ITF).</P>""")

        # log cycles control
        lo1.setColumnStretch(1, 1)
        self._wlogcycles_label = QLabel("Log cycles: ", self)
        lo1.addWidget(self._wlogcycles_label, 0, 1)
        #    self._wlogcycles = QwtWheel(self)
        #    self._wlogcycles.setTotalAngle(360)
        self._wlogcycles = QwtSlider(self)
        self._wlogcycles.setToolTip(
            """<P>Use this to change the log-base for the logarithmic intensity transfer function (ITF).</P>""")
        # This works around a stupid bug in QwtSliders -- see comments on histogram zoom wheel above
        self._wlogcycles_timer = QTimer(self)
        self._wlogcycles_timer.setSingleShot(True)
        self._wlogcycles_timer.setInterval(500)
        QObject.connect(self._wlogcycles_timer, SIGNAL("timeout()"), self._setIntensityLogCycles)
        lo1.addWidget(self._wlogcycles, 1, 1)
        self._wlogcycles.setRange(1., 10)
        self._wlogcycles.setStep(0.1)
        self._wlogcycles.setTracking(False)
        QObject.connect(self._wlogcycles, SIGNAL("valueChanged(double)"), self._setIntensityLogCycles)
        QObject.connect(self._wlogcycles, SIGNAL("sliderMoved(double)"), self._previewIntensityLogCycles)
        self._updating_imap = False

        # lock intensity map
        lo1 = QHBoxLayout()
        lo1.setContentsMargins(0, 0, 0, 0)
        lo0.addLayout(lo1, 0)
        #    lo1.addWidget(QLabel("Lock range accross",self))
        wlock = QCheckBox("Lock display range", self)
        wlock.setToolTip("""<P>If checked, then the intensity range will be locked. The ranges of all locked images
      change simultaneously.</P>""")
        lo1.addWidget(wlock)
        wlockall = QToolButton(self)
        wlockall.setIcon(pixmaps.locked.icon())
        wlockall.setText("Lock all to this")
        wlockall.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        wlockall.setAutoRaise(True)
        wlockall.setToolTip("""<P>Click this to lock together the intensity ranges of all images.</P>""")
        lo1.addWidget(wlockall)
        wunlockall = QToolButton(self)
        wunlockall.setIcon(pixmaps.unlocked.icon())
        wunlockall.setText("Unlock all")
        wunlockall.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        wunlockall.setAutoRaise(True)
        wunlockall.setToolTip("""<P>Click this to unlock the intensity ranges of all images.</P>""")
        lo1.addWidget(wunlockall)
        wlock.setChecked(self._rc.isDisplayRangeLocked())
        QObject.connect(wlock, SIGNAL("clicked(bool)"), self._rc.lockDisplayRange)
        QObject.connect(wlockall, SIGNAL("clicked()"),
                        self._currier.curry(self._imgman.lockAllDisplayRanges, self._rc))
        QObject.connect(wunlockall, SIGNAL("clicked()"), self._imgman.unlockAllDisplayRanges)
        QObject.connect(self._rc, SIGNAL("displayRangeLocked"), wlock.setChecked)

        #    self._wlock_imap_axis = [ QCheckBox(name,self) for iaxis,name,labels in sliced_axes ]
        #    for iw,w in enumerate(self._wlock_imap_axis):
        #      QObject.connect(w,SIGNAL("toggled(bool)"),self._currier.curry(self._rc.lockDisplayRangeForAxis,iw))
        #      lo1.addWidget(w,0)
        lo1.addStretch(1)

        # lo0.addWidget(Separator(self,"Colourmap"))
        # color bar
        self._colorbar = QwtPlot(self)
        lo0.addWidget(self._colorbar)
        self._colorbar.setAutoDelete(False)
        self._colorbar.setMinimumHeight(32)
        self._colorbar.enableAxis(QwtPlot.yLeft, False)
        self._colorbar.enableAxis(QwtPlot.xBottom, False)
        # color plot
        self._colorplot = QwtPlot(self)
        lo0.addWidget(self._colorplot)
        self._colorplot.setAutoDelete(False)
        self._colorplot.setMinimumHeight(64)
        self._colorplot.enableAxis(QwtPlot.yLeft, False)
        self._colorplot.enableAxis(QwtPlot.xBottom, False)
        # self._colorplot.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Preferred)
        self._colorbar.hide()
        self._colorplot.hide()
        # color controls
        lo1 = QHBoxLayout()
        lo1.setContentsMargins(0, 0, 0, 0)
        lo0.addLayout(lo1, 1)
        lo1.addWidget(QLabel("Colourmap:", self))
        # colormap list
        ### NB: use setIconSize() and icons in QComboBox!!!
        self._wcolmaps = QComboBox(self)
        self._wcolmaps.setIconSize(QSize(128, 16))
        self._wcolmaps.setToolTip("""<P>Use this to select a different colourmap.</P>""")
        for cmap in self._rc.getColormapList():
            self._wcolmaps.addItem(QIcon(cmap.makeQPixmap(128, 16)), cmap.name)
        lo1.addWidget(self._wcolmaps)
        QObject.connect(self._wcolmaps, SIGNAL("activated(int)"), self._rc.setColorMapNumber)
        # add widgetstack for colormap controls
        self._wcolmap_control_stack = QStackedWidget(self)
        self._wcolmap_control_blank = QWidget(self._wcolmap_control_stack)
        self._wcolmap_control_stack.addWidget(self._wcolmap_control_blank)
        lo0.addWidget(self._wcolmap_control_stack)
        self._colmap_controls = []
        # add controls to stack
        for index, cmap in enumerate(self._rc.getColormapList()):
            if isinstance(cmap, Colormaps.ColormapWithControls):
                controls = cmap.makeControlWidgets(self._wcolmap_control_stack)
                self._wcolmap_control_stack.addWidget(controls)
                QObject.connect(cmap, SIGNAL("colormapChanged"),
                                self._currier.curry(self._previewColormapParameters, index, cmap))
                QObject.connect(cmap, SIGNAL("colormapPreviewed"),
                                self._currier.curry(self._previewColormapParameters, index, cmap))
                self._colmap_controls.append(controls)
            else:
                self._colmap_controls.append(self._wcolmap_control_blank)

        # connect updates from renderControl and image
        self.image.connect(SIGNAL("slice"), self._updateImageSlice)
        QObject.connect(self._rc, SIGNAL("intensityMapChanged"), self._updateIntensityMap)
        QObject.connect(self._rc, SIGNAL("colorMapChanged"), self._updateColorMap)
        QObject.connect(self._rc, SIGNAL("dataSubsetChanged"), self._updateDataSubset)
        QObject.connect(self._rc, SIGNAL("displayRangeChanged"), self._updateDisplayRange)

        # update widgets
        self._setupHistogramPlot()
        self._updateDataSubset(*self._rc.currentSubset())
        self._updateColorMap(image.colorMap())
        self._updateIntensityMap(rc.currentIntensityMap(), rc.currentIntensityMapNumber())
        self._updateDisplayRange(*self._rc.displayRange())