Beispiel #1
0
 def createEditor(self, parent, option, index):
     """
     Creates different editors for different types of data
     """
     leafNode = index.internalPointer()
     if VERBOSE_CONFIG:
         print('\n\n')
         print('[DELEGATE] newEditor for %s at %s' %
               (leafNode, qindexstr(index)))
     if leafNode is not None and leafNode.is_combo:
         import guitool
         options = leafNode.valid_values
         curent_value = index.model().data(index)
         if VERBOSE_CONFIG:
             print('[DELEGATE] * current_value = %r' % (curent_value, ))
         editor = guitool.newComboBox(parent, options, default=curent_value)
         editor.currentIndexChanged['int'].connect(self.currentIndexChanged)
         editor.setAutoFillBackground(True)
         return editor
     elif leafNode is not None and leafNode.type_ is float:
         editor = QtGui.QDoubleSpinBox(parent)
         # TODO: min / max
         if False:
             editor.setMinimum(0.0)
             editor.setMaximum(1.0)
         editor.setSingleStep(0.1)
         editor.setAutoFillBackground(True)
         editor.setHidden(False)
         return editor
     elif leafNode is not None and leafNode.type_ is int:
         # TODO: Find a way for the user to enter a None into int boxes
         editor = QtGui.QSpinBox(parent)
         editor.setMinimum(-int(2**29))
         editor.setMaximum(int(2**29))
         if False:
             editor.setMinimum(0)
             editor.setMaximum(1)
         editor.setSingleStep(1)
         editor.setAutoFillBackground(True)
         editor.setHidden(False)
         return editor
     else:
         editor = super(ConfigValueDelegate,
                        self).createEditor(parent, option, index)
         editor.setAutoFillBackground(True)
         return editor
Beispiel #2
0
 def createEditor(self, parent, option, index):
     combo = QtGui.QComboBox(parent)
     combo.addItems(['option1', 'option2', 'option3'])
     #self.connect(combo.currentIndexChanged, self.currentIndexChanged)
     # FIXME: Change to newstyle signal slot
     self.connect(combo, QtCore.SIGNAL("currentIndexChanged(int)"), self,
                  QtCore.SLOT("currentIndexChanged()"))
     return combo
Beispiel #3
0
def get_monitor_geometries():
    ensure_app_is_running()
    monitor_geometries = {}
    desktop = QtGui.QDesktopWidget()
    for screenx in range(desktop.numScreens()):
        rect = desktop.availableGeometry(screen=screenx)
        geom = (rect.x(), rect.y(), rect.width(), rect.height())
        monitor_geometries[screenx] = geom
    return monitor_geometries
Beispiel #4
0
 def _init_components(ibswgt):
     """ Defines gui components """
     # Layout
     ibswgt.vlayout = QtGui.QVBoxLayout(ibswgt)
     # Create models and views
     ibswgt.view = IBEISTableView(parent=ibswgt)
     ibswgt.model = IBEISStripeModel(parent=ibswgt.view)
     ibswgt.proxy = StripeProxyModel(numduplicates=3)
     #ibswgt.proxy = QtGui.QIdentityProxyModel()
     ibswgt.proxy.setSourceModel(ibswgt.model)
     ibswgt.view.setModel(ibswgt.model)
Beispiel #5
0
    def _add_imageset_tab(widget, imageset_id, imageset_name):
        if imageset_id not in widget.imageset_id_list:
            tab_name = str(imageset_id) + ' - ' + str(imageset_name)
            widget.addTab(QtGui.QWidget(), tab_name)

            widget.imageset_id_list.append(imageset_id)
            index = len(widget.imageset_id_list) - 1
        else:
            index = widget.imageset_id_list.index(imageset_id)

        widget.setCurrentIndex(index)
        widget._on_change(index)
Beispiel #6
0
def newFileDialog(directory_, other_sidebar_dpaths=[], use_sidebar_cwd=True):
    qdlg = QtGui.QFileDialog()
    sidebar_urls = qdlg.sidebarUrls()[:]
    if use_sidebar_cwd:
        sidebar_urls.append(QtCore.QUrl.fromLocalFile(os.getcwd()))
    if directory_ is not None:
        sidebar_urls.append(QtCore.QUrl.fromLocalFile(directory_))
    sidebar_urls.extend(
        list(map(QtCore.QUrl.fromUserInput, other_sidebar_dpaths)))
    sidebar_urls = ut.unique(sidebar_urls)
    #print('sidebar_urls = %r' % (sidebar_urls,))
    qdlg.setSidebarUrls(sidebar_urls)
    return qdlg
Beispiel #7
0
 def paint(self, painter, option, index):
     # This method will be called every time a particular cell is
     # in view and that view is changed in some way. We ask the
     # delegates parent (in this case a table view) if the index
     # in question (the table cell) already has a widget associated
     # with it. If not, create one with the text for this index and
     # connect its clicked signal to a slot in the parent view so
     # we are notified when its used and can do something.
     if not self.parent().indexWidget(index):
         self.parent().setIndexWidget(
             index,
             QtGui.QPushButton(index.data().toString(),
                               self.parent(),
                               clicked=self.parent().cellButtonClicked))
Beispiel #8
0
def paint_button(painter, option, text='button', pressed=True, bgcolor=None,
                 fgcolor=None, clicked=None, button=None, view=None):
    #http://www.qtcentre.org/archive/index.php/t-31029.html
    opt = QtGui.QStyleOptionButton()
    opt.text = text
    opt.rect = option.rect
    opt.palette = option.palette
    if pressed:
        opt.state = QtGui.QStyle.State_Enabled | QtGui.QStyle.State_Sunken
    else:
        opt.state = QtGui.QStyle.State_Enabled | QtGui.QStyle.State_Raised

    #style = QtGui.Q Application.style()
    style = button.style()
    style.drawControl(QtGui.QStyle.CE_PushButton, opt, painter, button)
Beispiel #9
0
 def data(model, index, role=Qt.DisplayRole):
     """ Returns the data to display """
     if not index.isValid():
         return None
     flags = model.flags(index)
     if role == Qt.TextAlignmentRole:
         return model.get_column_alignment(index.column())
     if role == Qt.BackgroundRole and (flags & Qt.ItemIsEditable
                                       or flags & Qt.ItemIsUserCheckable):
         return QtCore.QVariant(QtGui.QColor(250, 240, 240))
     if role == Qt.DisplayRole or role == Qt.CheckStateRole:
         data = model.get_data(index)
         var = qtype.cast_into_qt(data, role, flags)
         return var
     else:
         return QtCore.QVariant()
Beispiel #10
0
def get_resolution_info(monitor_num=0):
    r"""
    Args:
        monitor_num (int): (default = 0)

    Returns:
        dict: info

    CommandLine:
        python -m plottool.screeninfo get_resolution_info --show

    Example:
        >>> # DISABLE_DOCTEST
        >>> from plottool.screeninfo import *  # NOQA
        >>> monitor_num = 0
        >>> info = get_resolution_info(monitor_num)
        >>> print('info = %s' % (ut.repr2(info, nl=True),))
        >>> info = get_resolution_info(1)
        >>> print('info = %s' % (ut.repr2(info, nl=True),))
    """
    ensure_app_is_running()
    desktop = QtGui.QDesktopWidget()
    screen = desktop.screen(monitor_num)
    ppi_x = screen.logicalDpiX()
    ppi_y = screen.logicalDpiY()
    dpi_x = screen.physicalDpiX()
    dpi_y = screen.physicalDpiY()
    rect = desktop.availableGeometry(screen=monitor_num)
    pixels_w = rect.width()
    pixels_h = rect.height()
    inches_w = (pixels_w / dpi_x)
    inches_h = (pixels_h / dpi_y)
    #pixel_density = dpi_x / ppi_x
    info = {
        'monitor_num': monitor_num,
        'ppi_x': ppi_x,
        'ppi_y': ppi_y,
        'dpi_x': dpi_x,
        'dpi_y': dpi_y,
        #'pixel_density': pixel_density,
        'inches_w': inches_w,
        'inches_h': inches_h,
        'pixels_w': pixels_w,
        'pixels_h': pixels_h,
    }
    return info
Beispiel #11
0
def _newMsgBox(msg='',
               title='',
               parent=None,
               options=None,
               cache_reply=False,
               resizable=False):
    if resizable:
        msgbox = ResizableMessageBox(parent)
    else:
        msgbox = QtGui.QMessageBox(parent)
    #msgbox.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    #std_buts = QtGui.QMessageBox.Close
    #std_buts = QtGui.QMessageBox.NoButton
    std_buts = QtGui.QMessageBox.Cancel
    msgbox.setStandardButtons(std_buts)
    msgbox.setWindowTitle(title)
    msgbox.setText(msg)
    msgbox.setModal(parent is not None)
    return msgbox
Beispiel #12
0
    def __init__(co_wgt, ibs, gid_list, parent=None, hack=False):
        print('[co_gui] Initializing')
        print('[co_gui] gid_list = %r' % (gid_list,))

        QtGui.QWidget.__init__(co_wgt, parent=parent)

        co_wgt.fnum = next_fnum()

        co_wgt.main_layout = QtGui.QVBoxLayout(co_wgt)

        co_wgt.text_layout = guitool.newWidget(co_wgt, orientation=Qt.Vertical, verticalStretch=10)
        co_wgt.main_layout.addWidget(co_wgt.text_layout)

        co_wgt.control_layout = guitool.newWidget(co_wgt, orientation=Qt.Vertical, verticalSizePolicy=QtGui.QSizePolicy.MinimumExpanding)
        co_wgt.main_layout.addWidget(co_wgt.control_layout)

        co_wgt.button_layout = guitool.newWidget(co_wgt, orientation=Qt.Horizontal)
        co_wgt.control_layout.addWidget(co_wgt.button_layout)

        co_wgt.combo_layout = guitool.newWidget(co_wgt, orientation=Qt.Horizontal)
        co_wgt.control_layout.addWidget(co_wgt.combo_layout)

        co_wgt.hack = hack  # hack for edting the time of a single image

        co_wgt.imfig = None
        co_wgt.imax = None

        co_wgt.dtime = None

        co_wgt.ibs = ibs
        co_wgt.gid_list = gid_list
        co_wgt.current_gindex = 0
        co_wgt.offset = 0
        # Set image datetime with first image
        co_wgt.get_image_datetime()
        co_wgt.add_label()
        co_wgt.add_combo_boxes()
        co_wgt.add_buttons()
        co_wgt.update_ui()
Beispiel #13
0
 def __init__(cltw,
              col_data_list=None,
              col_name_list=None,
              niceheader_list=None,
              col_type_list=None,
              col_edit_list=None,
              display_indices=False,
              col_sort_index=None,
              parent=None):
     QtGui.QWidget.__init__(cltw, parent)
     # Create vertical layout for the table to go into
     cltw.vert_layout = QtGui.QVBoxLayout(cltw)
     # Instansiate the AbstractItemModel
     cltw.model = ColumnListItemModel(parent=cltw)
     # Create a ColumnListTableView for the AbstractItemModel
     cltw.view = ColumnListTableView(cltw)
     cltw.view.setModel(cltw.model)
     cltw.vert_layout.addWidget(cltw.view)
     # Make sure we don't call a childs method
     ColumnListTableWidget.change_data(cltw, col_data_list, col_name_list,
                                       niceheader_list, col_type_list,
                                       col_edit_list, display_indices,
                                       col_sort_index)
Beispiel #14
0
 def __init__(widget,
              headers=None,
              parent=None,
              model_class=APIItemModel,
              view_class=APITableView,
              tblnice='APIItemWidget'):
     WIDGET_BASE.__init__(widget, parent)
     # Create vertical layout for the table to go into
     widget.vert_layout = QtGui.QVBoxLayout(widget)
     # Create a ColumnListTableView for the AbstractItemModel
     widget.view = view_class(parent=widget)
     # Instantiate the AbstractItemModel
     # FIXME: It is very bad to give the model a view.
     # Only the view should have a model
     widget.model = model_class(parent=widget.view)
     widget.view.setModel(widget.model)
     widget.vert_layout.addWidget(widget.view)
     widget.tblnice = tblnice
     if headers is not None:
         # Make sure we don't call a subclass method
         APIItemWidget.change_headers(widget, headers)
     widget.connect_signals()
     widget.api = None
Beispiel #15
0
def get_monitor_geom(monitor_num=0):
    r"""
    Args:
        monitor_num (int): (default = 0)

    Returns:
        tuple: geom

    CommandLine:
        python -m plottool.screeninfo get_monitor_geom --show

    Example:
        >>> # DISABLE_DOCTEST
        >>> from plottool.screeninfo import *  # NOQA
        >>> monitor_num = 0
        >>> geom = get_monitor_geom(monitor_num)
        >>> result = ('geom = %s' % (ut.repr2(geom),))
        >>> print(result)
    """
    ensure_app_is_running()
    desktop = QtGui.QDesktopWidget()
    rect = desktop.availableGeometry(screen=monitor_num)
    geom = (rect.x(), rect.y(), rect.width(), rect.height())
    return geom
Beispiel #16
0
def read_thumb_as_qimg(thumb_path):
    r"""
    Args:
        thumb_path (?):

    Returns:
        tuple: (qimg, width, height)

    CommandLine:
        python -m guitool.api_thumb_delegate --test-read_thumb_as_qimg --show

    Example:
        >>> # ENABLE_DOCTEST
        >>> from guitool.api_thumb_delegate import *  # NOQA
        >>> import guitool
        >>> # build test data
        >>> thumb_path = ut.grab_test_imgpath('carl.jpg')
        >>> # execute function
        >>> guitool.ensure_qtapp()
        >>> (qimg) = ut.memprof(read_thumb_as_qimg)(thumb_path)
        >>> if ut.show_was_requested():
        >>>    lbl = test_show_qimg(qimg)
        >>>    guitool.qtapp_loop()
        >>> # verify results
        >>> print(qimg)

    Timeit::
        %timeit np.dstack((npimg, np.full(npimg.shape[0:2], 255, dtype=np.uint8)))
        %timeit cv2.cvtColor(npimg, cv2.COLOR_BGR2BGRA)
        npimg1 = np.dstack((npimg, np.full(npimg.shape[0:2], 255, dtype=np.uint8)))
        # seems to be memory leak in cvtColor?
        npimg2 = cv2.cvtColor(npimg, cv2.COLOR_BGR2BGRA)

    """
    if VERBOSE_THUMB:
        print('[ThumbDelegate] Reading thumb as qimg. thumb_path=%r' % (thumb_path,))
    # Read thumbnail image and convert to 32bit aligned for Qt
    #if False:
    #    data  = np.dstack((npimg, np.full(npimg.shape[0:2], 255, dtype=np.uint8)))
    #if False:
    #    # Reading the npimage and then handing it off to Qt causes a memory
    #    # leak. The numpy array probably is never unallocated because qt doesn't
    #    # own it and it never loses its reference count
    #    #npimg = vt.imread(thumb_path, delete_if_corrupted=True)
    #    #print('npimg.dtype = %r, %r' % (npimg.shape, npimg.dtype))
    #    #npimg   = cv2.cvtColor(npimg, cv2.COLOR_BGR2BGRA)
    #    #format_ = QtGui.QImage.Format_ARGB32
    #    ##    #data    = npimg.astype(np.uint8)
    #    ##    #npimg   = np.dstack((npimg[:, :, 3], npimg[:, :, 0:2]))
    #    ##    #data    = npimg.astype(np.uint8)
    #    ##else:
    #    ## Memory seems to be no freed by the QImage?
    #    ##data = np.ascontiguousarray(npimg[:, :, ::-1].astype(np.uint8), dtype=np.uint8)
    #    ##data = np.ascontiguousarray(npimg[:, :, :].astype(np.uint8), dtype=np.uint8)
    #    #data = npimg
    #    ##format_ = QtGui.QImage.Format_RGB888
    #    #(height, width) = data.shape[0:2]
    #    #qimg    = QtGui.QImage(data, width, height, format_)
    #    #del npimg
    #    #del data
    #else:
    #format_ = QtGui.QImage.Format_ARGB32
    #qimg    = QtGui.QImage(thumb_path, format_)
    qimg    = QtGui.QImage(thumb_path)
    return qimg
Beispiel #17
0
def test_show_qimg(qimg):
    qpixmap = QtGui.QPixmap(qimg)
    lbl = QtGui.QLabel()
    lbl.setPixmap(qpixmap)
    lbl.show()   # show label with qim image
    return lbl
Beispiel #18
0
def _cacheReply(msgbox):
    dontPrompt = QtGui.QCheckBox('dont ask me again', parent=msgbox)
    dontPrompt.blockSignals(True)
    msgbox.addButton(dontPrompt, QtGui.QMessageBox.ActionRole)
    return dontPrompt
Beispiel #19
0
def user_option(parent=None,
                msg='msg',
                title='user_option',
                options=['Yes', 'No'],
                use_cache=False,
                default=None,
                detailed_msg=None):
    """
    Prompts user with several options with ability to save decision

    Args:
        parent (None):
        msg (str):
        title (str):
        options (list):
        use_cache (bool):
        default (str): default option

    Returns:
        str: reply

    CommandLine:
        python -m guitool.guitool_dialogs --test-user_option

    Example:
        >>> # GUI_DOCTEST
        >>> from guitool.guitool_dialogs import *  # NOQA
        >>> import guitool
        >>> guitool.ensure_qtapp()
        >>> parent = None
        >>> msg = 'msg'
        >>> title = 'user_option'
        >>> options = ['Yes', 'No']
        >>> use_cache = False
        >>> default = 'Yes'
        >>> # execute function
        >>> detailed_msg = 'hi'
        >>> reply = user_option(parent, msg, title, options, use_cache, default, detailed_msg)
        >>> result = str(reply)
        >>> print(result)
        >>> ut.quit_if_noshow()
        >>> #guitool.guitool_main.qtapp_loop()
    """
    if ut.VERBOSE:
        print('[gt] user_option:\n %r: %s' % (title, msg))
    # Recall decision
    cache_id = title + msg
    if use_cache:
        reply = _guitool_cache_read(cache_id, default=None)
        if reply is not None:
            return reply
    # Create message box
    msgbox = _newMsgBox(msg, title, parent, resizable=detailed_msg is not None)
    #     _addOptions(msgbox, options)
    # def _addOptions(msgbox, options):
    #msgbox.addButton(QtGui.QMessageBox.Close)
    options = list(options)[::-1]
    for opt in options:
        role = QtGui.QMessageBox.ApplyRole
        msgbox.addButton(QtGui.QPushButton(opt), role)
    # Set default button
    if default is not None:
        assert default in options, ('default=%r is not in options=%r' %
                                    (default, options))
        for qbutton in msgbox.buttons():
            if default == qbutton.text():
                msgbox.setDefaultButton(qbutton)
    if use_cache:
        # Add a remember me option if caching is on
        dontPrompt = _cacheReply(msgbox)

    if detailed_msg is not None:
        msgbox.setDetailedText(detailed_msg)
    # Wait for output
    optx = msgbox.exec_()
    if optx == QtGui.QMessageBox.Cancel:
        # User Canceled
        return None
    try:
        # User Selected an option
        reply = options[optx]
    except KeyError as ex:
        # This should be unreachable code.
        print('[gt] USER OPTION EXCEPTION !')
        print('[gt] optx = %r' % optx)
        print('[gt] options = %r' % options)
        print('[gt] ex = %r' % ex)
        raise
    # Remember decision if caching is on
    if use_cache and dontPrompt.isChecked():
        _guitool_cache_write(cache_id, reply)
    # Close the message box
    del msgbox
    return reply
Beispiel #20
0
    def data(model, qtindex, role=Qt.DisplayRole, **kwargs):
        """
        Depending on the role, returns either data or how to display data
        Returns the data stored under the given role for the item referred to by
        the index.

        Note:
            If you do not have a value to return, return None
        """
        if not qtindex.isValid():
            return None
        flags = model.flags(qtindex)
        #row = qtindex.row()
        col = qtindex.column()
        node = qtindex.internalPointer()
        if model.col_level_list[col] != node.get_level():
            return QVariantHack()
        type_ = model._get_type(col)

        #if row >= model.rowCount():
        #    # Yuck.
        #    print('[item_model] Yuck. row=%r excedes rowCount=%r' %
        #          (row, model.rowCount()))
        #    return QVariantHack()

        #if role == Qt.SizeHintRole:
        #    #printDBG('REQUEST QSIZE FOR: ' + qtype.ItemDataRoles[role])
        #    return QtCore.QSize(64, 64)
        #
        # Specify Text Alignment Role
        if role == Qt.TextAlignmentRole:
            if type_ in qtype.QT_IMAGE_TYPES:
                value = Qt.AlignRight | Qt.AlignVCenter
            elif type_ in qtype.QT_BUTTON_TYPES:
                value = Qt.AlignRight | Qt.AlignVCenter
            elif type_ in ut.VALID_FLOAT_TYPES:
                value = Qt.AlignRight | Qt.AlignVCenter
            else:
                value = Qt.AlignHCenter | Qt.AlignVCenter
            return value
        #
        # Specify Background Rule
        elif role == Qt.BackgroundRole:
            value = model._get_bgrole_value(qtindex)
            if value is not None:
                return value
            if flags & Qt.ItemIsEditable:
                # Editable fields are colored
                return QVariantHack(model.EditableItemColor)
            elif flags & Qt.ItemIsUserCheckable:
                # Checkable color depends on the truth value
                data = model._get_data(qtindex, **kwargs)
                if data:
                    return QVariantHack(model.TrueItemColor)
                else:
                    return QVariantHack(model.FalseItemColor)
            else:
                pass
        #
        # Specify Foreground Role
        elif role == Qt.ForegroundRole:
            if flags & Qt.ItemIsEditable:
                return QtGui.QBrush(QtGui.QColor(0, 0, 0))

        # Specify Decoration Role (superceded by thumbdelegate)
        # elif role == Qt.DecorationRole and type_ in qtype.QT_IMAGE_TYPES:

        # Specify CheckState Role:
        if role == Qt.CheckStateRole:
            if flags & Qt.ItemIsUserCheckable:
                data = model._get_data(qtindex, **kwargs)
                return Qt.Checked if data else Qt.Unchecked
        #
        # Return the data to edit or display
        elif role in (Qt.DisplayRole, Qt.EditRole):
            # For types displayed with custom delegates do not cast data into a
            # qvariant. This includes PIXMAP, BUTTON, and COMBO
            if type_ in qtype.QT_DELEGATE_TYPES:
                data = model._get_data(qtindex, **kwargs)
                #print(data)
                return data
            else:
                # Display data with default delegate by casting to a qvariant
                data = model._get_data(qtindex, **kwargs)
                value = qtype.cast_into_qt(data)
                return value
        else:
            #import builtins
            #role_name = qtype.ItemDataRoles[role]
            #builtins.print('UNHANDLED ROLE=%r' % role_name)
            pass
        # else return None
        return QVariantHack()
Beispiel #21
0
def numpy_to_qicon(npimg):
    qpixmap = numpy_to_qpixmap(npimg)
    qicon = QtGui.QIcon(qpixmap)
    return qicon
Beispiel #22
0
def rgb_to_qcolor(rgb):
    return QtGui.QColor(*rgb[0:3])
Beispiel #23
0
    def paint(self, painter, option, index):
        # Get Item Data
        # value = index.data(QtCore.Qt.DisplayRole).toInt()[0]
        leafNode = index.internalPointer()
        if (VERBOSE_CONFIG and False):
            print('[DELEGATE] * painting editor for %s at %s' %
                  (leafNode, qindexstr(index)))
        if leafNode.is_combo:
            #print('[DELEGATE] * painting editor for %s at %s' % (leafNode, qindexstr(index)))
            #painter.save()
            curent_value = six.text_type(index.model().data(index))
            # fill style options with item data
            app = QtCore.QCoreApplication.instance()
            #print('app = %r' % (app,))
            #print('style = %r' % (style,))
            style = app.style()
            #style = QtGui.QApplication.style()
            opt = QtGui.QStyleOptionComboBox()
            opt.currentText = curent_value
            opt.rect = option.rect
            #opt.rect.setWidth(400)
            #print('opt.rect = %r' % (opt.rect,))
            opt.editable = False

            #style.State style.StateFlag style.State_NoChange style.State_Sibling
            #style.State_Active style.State_FocusAtBorder style.State_None
            #style.State_Small style.State_AutoRaise style.State_HasFocus
            #style.State_Off style.State_Sunken style.State_Bottom
            #style.State_Horizontal style.State_On style.State_Top
            #style.State_Children style.State_Item style.State_Open
            #style.State_UpArrow style.State_DownArrow
            #style.State_KeyboardFocusChange style.State_Raised style.State_Window
            #style.State_Editing style.State_Mini style.State_ReadOnly
            #style.State_Enabled style.State_MouseOver style.State_Selected

            #opt.state |= style.State_Raised
            #opt.state |= style.State_UpArrow
            #opt.state |= style.State_AutoRaise
            #opt.state |= style.State_Active
            #opt.state |= style.State_Editing
            #opt.state |= style.State_Enabled
            #opt.state |= style.State_On
            #opt.state |= style.State_Open
            #opt.state |= style.State_HasFocus
            #opt.state |= style.State_FocusAtBorder
            #opt.state |= style.State_Selected

            #painter.drawText(option.rect, Qt.AlignLeft, "FOOBAR")
            #print('opt.state = %r' % (opt.state,))

            if leafNode.qt_is_editable():
                opt.state |= style.State_On
                opt.state |= style.State_Enabled
                opt.state = style.State_Enabled | style.State_Active
            #else:
            #opt.state = style.State_Enabled | style.State_Active

            #self.initStyleOption(opt)

            #'currentIcon': <PyQt4.QtGui.QIcon object at 0x7fb19681b8a0>,
            #'currentText': '',
            #'direction': 0,
            #'editable': False,
            #'frame': True,
            #'iconSize': PyQt4.QtCore.QSize(-1, -1),
            #'palette': <PyQt4.QtGui.QPalette object at 0x7fb1959666e0>,
            #'popupRect': PyQt4.QtCore.QRect(),
            #'rect': PyQt4.QtCore.QRect(),
            #'state': <PyQt4.QtGui.State object at 0x7fb195966848>,
            #'activeSubControls': <PyQt4.QtGui.SubControls object at 0x7fb195966578>,
            #'subControls': <PyQt4.QtGui.SubControls object at 0x7fb1959668c0>,

            opt.subControls = QtGui.QStyle.SC_All
            #print('QtGui.QStyle.SC_All = %r' % (QtGui.QStyle.SC_All,))
            #print('opt.subControls = %r' % (opt.subControls,))

            # draw item data as ComboBox
            #element = QtGui.QStyle.CE_ItemViewItem
            element = QtGui.QStyle.CE_ComboBoxLabel
            control = QtGui.QStyle.CC_ComboBox

            #QtGui.QStyle.SC_ComboBoxArrow
            #QtGui.QStyle.SC_ComboBoxEditField
            #QtGui.QStyle.SC_ComboBoxFrame
            #QtGui.QStyle.SC_ComboBoxListBoxPopup

            #style.drawPrimitive(QtGui.QStyle.PE_PanelButtonBevel, opt, painter)
            # Do I need to draw sub controls?
            style.drawControl(element, opt, painter)
            style.drawComplexControl(control, opt, painter)
            #self.drawDisplay(painter, opt, opt.rect, opt.currentText)
            #self.drawFocus(painter, opt, opt.rect)
            #QtGui.QItemDelegate
            #painter.restore()
            #return super(ConfigValueDelegate, self).paint(painter, option, index)
        #elif leafNode is not None and leafNode.type_ is int:
        #    curent_value = six.text_type(index.model().data(index))
        #    # fill style options with item data
        #    style = QtGui.QApplication.style()
        #    opt = QtGui.QStyleOptionSpinBox()
        #    opt.currentText = curent_value
        #    opt.rect = option.rect
        #    #opt.editable = False
        #    if leafNode.qt_is_editable():
        #        opt.state |= style.State_Enabled
        #    element = QtGui.QStyle.CE_ItemViewItem
        #    control = QtGui.QStyle.CC_SpinBox
        #    style.drawControl(element, opt, painter)
        #    style.drawComplexControl(control, opt, painter)
        else:
            return super(ConfigValueDelegate,
                         self).paint(painter, option, index)
Beispiel #24
0
        widget.vlayout.addWidget(widget._imageset_view)

    def _change_imageset(widget, imageset_id):
        widget._image_view._change_imageset(imageset_id)

    def _add_imageset_tab(widget, imageset_id, imageset_name):
        widget._tab_widget._add_imageset_tab(imageset_id, imageset_name)

    def _update_imageset_tab_name(widget, imageset_id, imageset_name):
        widget._tab_widget._update_imageset_tab_name(imageset_id,
                                                     imageset_name)


if __name__ == '__main__':
    import sys
    import signal
    import guitool

    def _on_ctrl_c(signal, frame):
        print('Caught ctrl+c')
        sys.exit(0)

    signal.signal(signal.SIGINT, _on_ctrl_c)
    app = QtGui.QApplication(sys.argv)
    widget = DummyWidget()
    widget.show()
    widget.timer = guitool.ping_python_interpreter()
    widget.raise_()
    sys.exit(app.exec_())
    signal.signal(signal.SIGINT, signal.SIG_DFL)  # reset ctrl+c behavior
Beispiel #25
0
def rgb_to_qbrush(rgb):
    return QtGui.QBrush(rgb_to_qcolor(rgb))
Beispiel #26
0
class APIItemModel(API_MODEL_BASE):
    """
    Item model for displaying a list of columns

    Attributes:
        iders         (list) : functions that return ids for setters and getters
        col_name_list (list) : keys or SQL-like name for column to reference
                        abstracted data storage using getters and setters
        col_type_list (list) : column value (Python) types
        col_nice_list (list) : well-formatted names of the columns
        col_edit_list (list) : booleans for if column should be editable

        col_setter_list (list) : setter functions
        col_getter_list (list) : getter functions

        col_sort_index (int) : index into col_name_list for sorting
        col_sort_reverse (bool) : flag to reverse the sort ordering
    """
    _rows_updated = signal_(str, int)
    EditableItemColor = QtGui.QColor(242, 242, 255)
    #EditableItemColor = QtGui.QColor(200, 200, 255)
    TrueItemColor     = QtGui.QColor(230, 250, 230)
    FalseItemColor    = QtGui.QColor(250, 230, 230)

    def _set_context_id(self, id_):
        self._context_id = id_

    def _get_context_id(self):
        return self._context_id

    def _set_changeblocked(self, changeblocked_):
        self._changeblocked = changeblocked_

    def _get_changeblocked(self):
        return self._changeblocked
    #
    # Non-Qt Init Functions
    def __init__(model, headers=None, parent=None):
        if VERBOSE:
            print('[APIItemModel] __init__')
        model.view = parent
        API_MODEL_BASE.__init__(model, parent=parent)
        # Internal Flags
        model._abouttochange   = False
        model._context_id      = None
        model._haschanged      = True
        model._changeblocked   = False
        # Model Data And Accessors
        model.name             = 'None'
        model.nice             = 'None'
        model.iders            = [lambda: []]
        model.col_visible_list = []
        model.col_name_list    = []
        model.col_type_list    = []
        model.col_nice_list    = []
        model.col_edit_list    = []
        model.col_setter_list  = []
        model.col_getter_list  = []
        model.col_level_list   = []
        model.col_bgrole_getter_list = None
        model.col_sort_index   = None
        model.col_sort_reverse = False
        model.level_index_list = []
        model.cache = None  # FIXME: This is not sustainable
        model.scope_hack_list = []
        model.root_node = _atn.TreeNode(-1, None, -1)
        # Initialize member variables
        #model._about_to_change()
        model.headers = headers  # save the headers

        model.ider_filters = None

        model.lazy_updater = None
        if headers is not None:
            model._update_headers(**headers)

    def set_ider_filters(model, ider_filters):
        """  Used to induce a filter on the rows, needs call of udpate rows after """
        model.ider_filters = ider_filters

    def get_iders(model):
        #def filtfun_test(x_list):
        #    return [x for x in x_list if x % 2 == 0]
        #model.name == 'annotations'
        #if len(model.iders) == 1:
        #    model.ider_filters = [filtfun_test]

        if model.ider_filters is None:
            ider_list = model.iders
        else:
            assert len(model.ider_filters) == len(model.iders), 'bad filters'
            #ider_list =  [lambda: filtfn(ider()) for filtfn, ider in zip(model.ider_filters, model.iders)]
            #with ut.embed_on_exception_context:
            def wrap_ider(ider, filtfn):
                def wrapped_ider(*args, **kwargs):
                    return filtfn(ider(*args, **kwargs))
                return wrapped_ider

            ider_list =  [
                #ider
                wrap_ider(ider, filtfn)
                #lambda *args: filtfn(ider(*args))
                for filtfn, ider in
                zip(model.ider_filters, model.iders)
            ]
        return ider_list

    #@profile
    @updater
    def _update_headers(model, **headers):
        if VERBOSE:
            print('[APIItemModel] _update_headers')
        iders            = headers.get('iders', None)
        name             = headers.get('name', None)
        nice             = headers.get('nice', None)
        #print('[api_model] UPDATE HEADERS: %r' % (name,))
        col_name_list    = headers.get('col_name_list', None)
        col_type_list    = headers.get('col_type_list', None)
        col_nice_list    = headers.get('col_nice_list', None)
        col_edit_list    = headers.get('col_edit_list', None)
        col_setter_list  = headers.get('col_setter_list', None)
        col_getter_list  = headers.get('col_getter_list', None)
        col_level_list   = headers.get('col_level_list', None)
        #col_sort_index   = headers.get('col_sort_index', -1)
        col_sort_index   = headers.get('col_sort_index', 0)
        col_sort_reverse = headers.get('col_sort_reverse', False)
        # New for dynamically getting non-data roles for each row
        col_bgrole_getter_list  = headers.get('col_bgrole_getter_list', None)
        col_visible_list = headers.get('col_visible_list', None)
        model.cache = {}  # FIXME: This is not sustainable
        model.name = str(name)
        model.nice = str(nice)
        # Initialize class
        model._set_iders(iders)
        model._set_col_name_type(col_name_list, col_type_list)
        model._set_col_nice(col_nice_list)
        model._set_col_edit(col_edit_list)
        model._set_col_setter(col_setter_list)
        model._set_col_getter(col_getter_list)
        model._set_col_bgrole_getter(col_bgrole_getter_list)
        model._set_col_visible_list(col_visible_list)

        model._set_col_level(col_level_list)
        # calls model._update_rows()
        model._set_sort(col_sort_index, col_sort_reverse, rebuild_structure=True)

    #@profile
    @updater
    def _update_rows(model, rebuild_structure=True):
        """
        Uses the current ider and col_sort_index to create
        row_indices
        """
        if VERBOSE:
            print('[APIItemModel] +-----------')
            print('[APIItemModel] _update_rows')
        # this is not slow
        #with ut.Timer('update_rows'):
        #printDBG('UPDATE ROWS!')
        #print('UPDATE ROWS!')
        #print('num_rows=%r' % len(model.col_level_list))
        #print('UPDATE model(%s) rows' % model.name)
        #print('[api_model] UPDATE ROWS: %r' % (model.name,))
        #print(ut.get_caller_name(range(4, 12)))
        if len(model.col_level_list) == 0:
            return
        #old_root = model.root_node  # NOQA
        if rebuild_structure:
            #with ut.Timer('[%s] _update_rows: %r' %
            #                 ('cyth' if _atn.CYTHONIZED else 'pyth',
            #                  model.name,), newline=False):
                model.root_node = _atn.build_internal_structure(model)
        #print('-----')
        #def lazy_update_rows():
        #    with ut.Timer('lazy updater: %r' % (model.name,)):
        #        printDBG('[model] calling lazy updater: %r' % (model.name,))
        # REMOVING LAZY FUNCTION BECAUSE IT MIGHT HAVE CAUSED PROBLEMS
        #with ut.Timer('[%s] _update_rows2: %r' %
        #                 ('cyth' if _atn.CYTHONIZED else 'pyth',
        #                  model.name,), newline=False):
        if VERBOSE:
            print('[APIItemModel] lazy_update_rows')
        model.level_index_list = []
        sort_index = 0 if model.col_sort_index is None else model.col_sort_index
        #print('[item_model] sort_index=%r' % (sort_index,))
        children = model.root_node.get_children()  # THIS IS THE LINE THAT TAKES FOREVER
        id_list = [child.get_id() for child in children]
        #print('ids_ generated')
        nodes = []
        if len(id_list) != 0:
            if VERBOSE:
                print('[APIItemModel] lazy_update_rows len(id_list) = %r' % (len(id_list)))
            # start sort
            if model.col_sort_index is not None:
                type_ = model.col_type_list[sort_index]
                getter = model.col_getter_list[sort_index]
                values = getter(id_list)
                if type_ == 'PIXMAP':
                    # TODO: find a better sorting metric for pixmaps
                    values = ut.get_list_column(values, 0)
                #print('values got')
            else:
                type_ = int
                values = id_list
            reverse = model.col_sort_reverse

            #ut.embed()
            # <NUMPY MULTIARRAY SORT>
            #with ut.embed_on_exception_context:
            if type_ is float:
                values = np.array(ut.replace_nones(values, np.nan))
                #values = np.array(values)
                values[np.isnan(values)] = -np.inf  # Force nan to be the smallest number
            import vtool as vt
            sortx = vt.argsort_records([values, id_list], reverse=reverse)
            #sorting_records = np.rec.fromarrays([values, id_list])
            #sort_stride = (-reverse * 2) + 1
            #sortx = sorting_records.argsort()[::sort_stride]
            # </NUMPY MULTIARRAY SORT>
            nodes = ut.take(children, sortx)

            #sorted_pairs = sorted(zip(values, id_list, children), reverse=reverse)
            #nodes = [child for (value, id_, child) in sorted_pairs]
            level = model.col_level_list[sort_index]
            #print("row_indices sorted")
            if level == 0:
                model.root_node.set_children(nodes)
            # end sort
        if ut.USE_ASSERT:
            assert nodes is not None, 'no indices'
        model.level_index_list = nodes
        #if VERBOSE:
        #    print('[APIItemModel] lazy_update_rows emmiting _rows_updated')

        # EMIT THE NUMERR OF ROWS AND THE NAME OF FOR THE VIEW TO DISPLAY
        model._rows_updated.emit(model.name, len(model.level_index_list))

        # lazy method didn't work. Eagerly evaluate
        #lazy_update_rows()
        # HACK TO MAKE SURE TREE NODES DONT DELETE THEMSELVES
        #if VERBOSE:
        #    print('[APIItemModel] build_scope_hack_list')
        # SCOPE HACK SEEMS TO HAVE NOT HALPED
        #model.scope_hack_list = []
        #_atn.build_scope_hack_list(model.root_node, model.scope_hack_list)
        #model.lazy_updater = lazy_update_rows
        #print("Rows updated")
        if VERBOSE:
            print('[APIItemModel] finished _update_rows')
            print('[APIItemModel] L__________')
    #del old_root

    #@profile
    def lazy_checks(model):
        if model.lazy_updater is not None:
            print('[model] lazy update %r caller %r: ' %
                  (model.name, ut.get_caller_name(N=range(4))))
            model.lazy_updater()
            model.lazy_updater = None

    @updater
    def _set_iders(model, iders=None):
        """ sets iders """
        if VERBOSE:
            print('[APIItemModel] _set_iders')
        if iders is None:
            iders = []
        if ut.USE_ASSERT:
            assert ut.is_list(iders), 'bad type: %r' % type(iders)
            for index, ider in enumerate(iders):
                assert ut.is_funclike(ider), 'bad type at index %r: %r' % (index, type(ider))
        #printDBG('NEW IDER')
        model.iders = iders

    @updater
    def _set_col_name_type(model, col_name_list=None, col_type_list=None):
        if VERBOSE:
            print('[APIItemModel] _set_col_name_type')
        if col_name_list is None:
            col_name_list = []
        if col_type_list is None:
            col_type_list = []
        if ut.USE_ASSERT:
            assert len(col_name_list) == len(col_type_list), \
                'inconsistent colnametype'
        model.col_name_list = col_name_list
        model.col_type_list = col_type_list

    @updater
    def _set_col_nice(model, col_nice_list=None):
        if col_nice_list is None:
            col_nice_list = model.col_name_list[:]
        if ut.USE_ASSERT:
            assert len(model.col_name_list) == len(col_nice_list), \
                'inconsistent colnice'
        model.col_nice_list = col_nice_list

    @default_method_decorator
    def _set_col_edit(model, col_edit_list=None):
        if col_edit_list is None:
            col_edit_list = [False] * len(model.col_name_list)
        if ut.USE_ASSERT:
            assert len(model.col_name_list) == len(col_edit_list), \
                'inconsistent coledit'
        model.col_edit_list = col_edit_list

    @default_method_decorator
    def _set_col_setter(model, col_setter_list=None):
        if VERBOSE:
            print('[APIItemModel] _set_col_setter')
        if col_setter_list is None:
            col_setter_list = []
        if ut.USE_ASSERT:
            assert len(model.col_name_list) == len(col_setter_list), \
                'inconsistent colsetter'
        model.col_setter_list = col_setter_list

    @default_method_decorator
    def _set_col_getter(model, col_getter_list=None):
        if VERBOSE:
            print('[APIItemModel] _set_col_getter')
        if col_getter_list is None:
            col_getter_list = []
        if ut.USE_ASSERT:
            assert len(model.col_name_list) == len(col_getter_list), \
                'inconsistent colgetter'
        model.col_getter_list = col_getter_list

    @default_method_decorator
    def _set_col_bgrole_getter(model, col_bgrole_getter_list=None):
        """ background rolegetter will be used for metadata like column color """
        if col_bgrole_getter_list is None:
            model.col_bgrole_getter_list = [None] * len(model.col_name_list)
        else:
            if ut.USE_ASSERT:
                assert len(col_bgrole_getter_list) == len(model.col_name_list), \
                    'inconsistent col_bgrole_getter_list'
            model.col_bgrole_getter_list = col_bgrole_getter_list

    @default_method_decorator
    def _set_col_visible_list(model, col_visible_list=None):
        """ used to turn columns off dynamically """
        if col_visible_list is None:
            model.col_visible_list = [True] * len(model.col_name_list)
        else:
            if ut.USE_ASSERT:
                assert len(col_visible_list) == len(model.col_name_list), \
                    'inconsistent col_visible_list'
            model.col_visible_list = col_visible_list

    @default_method_decorator
    def _set_col_level(model, col_level_list=None):
        if VERBOSE:
            print('[APIItemModel] _set_col_level')
        if col_level_list is None:
            col_level_list = [0] * len(model.col_name_list)
        if ut.USE_ASSERT:
            assert len(model.col_name_list) == len(col_level_list), \
                'inconsistent collevel'
        model.col_level_list = col_level_list

    @updater
    def _set_sort(model, col_sort_index, col_sort_reverse=False, rebuild_structure=False):
        if VERBOSE:
            print('[APIItemModel] _set_sort, index=%r reverse=%r, rebuild=%r' %
                  (col_sort_index, col_sort_reverse, rebuild_structure,))
        #with ut.Timer('set_sort'):
        #printDBG('SET SORT')
        if len(model.col_name_list) > 0:
            if ut.USE_ASSERT:
                assert isinstance(col_sort_index, int) and col_sort_index < len(model.col_name_list), \
                    'sort index out of bounds by: %r' % col_sort_index
            model.col_sort_index = col_sort_index
            model.col_sort_reverse = col_sort_reverse
            # Update the row-id order
            model._update_rows(rebuild_structure=rebuild_structure)

    #------------------------------------
    # --- Data maintainence functions ---
    #------------------------------------

    @default_method_decorator
    def _about_to_change(model, force=False):
        #N = range(0, 10)  # NOQA
        if force or (not model._abouttochange and not model._changeblocked):
            #printDBG('ABOUT TO CHANGE: %r' % (model.name,))
            #printDBG('caller=%r' % (ut.get_caller_name(N=N)))
            model._abouttochange = True
            model.layoutAboutToBeChanged.emit()
            return True
        else:
            #printDBG('NOT ABOUT TO CHANGE')
            return False

    @default_method_decorator
    def _change(model, force=False):
        #N = range(0, 10)  # NOQA
        if force or (model._abouttochange and not model._changeblocked):
            #printDBG('LAYOUT CHANGED:  %r' % (model.name,))
            #printDBG('caller=%r' % (ut.get_caller_name(N=N)))
            #model._abouttochange = False
            model._abouttochange = False
            #printDBG('CHANGE: CACHE INVALIDATED!')
            model.cache = {}
            model.layoutChanged.emit()
            return True
        else:
            #printDBG('NOT CHANGING')
            #print('NOT LAYOU CHANGED: %r, caller=%r' % (model.name, ut.get_caller_name(N=N)))
            return False

    @default_method_decorator
    def _update(model, newrows=False):
        #if newrows:
        model._update_rows()
        #printDBG('UPDATE: CACHE INVALIDATED!')
        model.cache = {}

    #def _use_ider(model, level):
    #    if level == 0:
    #        return model.iders[level]()
    #    else:
    #        return model.iders[level](model._use_ider(level - 1))

    def _use_ider(model, level=0):
        if level == 0:
            return model.iders[level]()
        else:
            parent_ids = model._use_ider(level - 1)
            level_ider = model.iders[level]
            return level_ider(parent_ids)

    def get_row_from_id(model, _id):
        r"""
        returns the row if an _id from the iders list

        Args:
            _id (int): sqlrowid

        Returns:
            int: row
        """
        row = model.root_node.find_row_from_id(_id)
        return row

    def get_row_and_qtindex_from_id(model, _id):
        """ uses an sqlrowid (from iders) to get a qtindex """
        row = model.get_row_from_id(_id)
        qtindex = model.index(row, 0) if row is not None else None
        return qtindex, row

    #----------------------------------
    # --- API Convineince Functions ---
    #----------------------------------

    @default_method_decorator
    def get_header_data(model, colname, qtindex):
        """ Use _get_data if the column number is known """
        # <HACK>
        # Hacked to only work on tables. Should be in terms of qtindex
        row = qtindex.row()
        if ut.USE_ASSERT:
            assert max(model.col_level_list) == 0, "Must be a table. Input is a tree"
        col = model.col_name_list.index(colname)
        id_ = model.root_node[row].get_id()
        getter = model.col_getter_list[col]
        value = getter(id_)
        return value
        # </HACK>

    @default_method_decorator
    def get_header_name(model, column):
        # TODO: use qtindex?
        colname = model.col_name_list[column]
        return colname

    @default_method_decorator
    def _get_level(model, qtindex):
        node = qtindex.internalPointer()
        if node is None:
            return -1
        level = node.get_level()
        #level = model.col_level_list[column]
        return level

    #--------------------------------
    # --- API Interface Functions ---
    #--------------------------------

    @default_method_decorator
    def _get_col_align(model, col):
        if ut.USE_ASSERT:
            assert col is not None, 'bad column'
        raise NotImplementedError('_get_col_align')

    @default_method_decorator
    def _get_row_id(model, qtindex=QtCore.QModelIndex()):
        """
        returns the id (specified by iders i.e. an ibeis rowid) from qtindex
        """
        if qtindex.isValid():
            node = qtindex.internalPointer()
            if ut.USE_ASSERT:
                try:
                    assert isinstance(node, _atn.TreeNode), 'type(node)=%r, node=%r' % (type(node), node)
                except AssertionError as ex:
                    ut.printex(ex, 'error in _get_row_id', keys=['model', 'qtindex', 'node'])
                    raise
            try:
                id_ = node.get_id()
            except AttributeError as ex:
                ut.printex(ex, key_list=['node', 'model', 'qtindex'])
                raise
            return id_

    @default_method_decorator
    def _get_adjacent_qtindex(model, qtindex=QtCore.QModelIndex(), offset=1):
        # check qtindex
        if not qtindex.isValid():
            return None
        node = qtindex.internalPointer()
        # check node
        try:
            if ut.USE_ASSERT:
                assert isinstance(node, _atn.TreeNode), type(node)
        except AssertionError as ex:
            ut.printex(ex, key_list=['node'], pad_stdout=True)
            raise
        # get node parent
        try:
            node_parent = node.get_parent()
        except Exception as ex:
            ut.printex(ex, key_list=['node'], reraise=False, pad_stdout=True)
            raise
        # parent_node check
        if node_parent is None:
            print('[model._get_adjacent_qtindex] node_parent is None!')
            return None
        # Offset to find the next qtindex
        next_index = node_parent.child_index(node) + offset
        nChildren = node_parent.get_num_children()
        # check next index validitiy
        if next_index >= 0 and next_index < nChildren:
            next_node = node_parent.get_child(next_index)
            next_level = next_node.get_level()
            col = model.col_level_list.index(next_level)
            row = next_node.get_row()
            # Create qtindex for the adjacent note
            parent_qtindex = model.parent(qtindex)
            next_qtindex = model.index(row, col, parent_qtindex)
            return next_qtindex
        else:
            # There is no adjacent node
            return None

    @default_method_decorator
    def _get_type(model, col):
        return model.col_type_list[col]

    @default_method_decorator
    def _get_bgrole_value(model, qtindex):
        """ Gets the background role if specified """
        col = qtindex.column()
        bgrole_getter = model.col_bgrole_getter_list[col]
        if bgrole_getter is None:
            return None
        row_id = model._get_row_id(qtindex)  # row_id w.r.t. to sorting
        color = bgrole_getter(row_id)
        if color is None:
            return None
        val = qtype.to_qcolor(color)
        return val

    @default_method_decorator
    def _get_data(model, qtindex, **kwargs):
        #row = qtindex.row()
        col = qtindex.column()
        row_id = model._get_row_id(qtindex)  # row_id w.r.t. to sorting
        getter = model.col_getter_list[col]  # getter for this column
        # Using this getter may not be thread safe
        try:
            # Should this work around decorators?
            #data = getter((row_id,), **kwargs)[0]
            data = getter(row_id, **kwargs)
        except Exception as ex:
            ut.printex(
                ex,
                '[api_item_model] problem getting in column %r' % (col,),
                keys=['model.name', 'getter', 'row_id', 'col', 'qtindex'])
            #getting from: %r' % ut.util_str.get_callable_name(getter))
            raise
        # <HACK: MODEL_CACHE>
        #cachekey = (row_id, col)
        #try:
        #    if True:  # Cache is disabled
        #        raise KeyError('')
        #    #data = model.cache[cachekey]
        #except KeyError:
        #    data = getter(row_id)
        #    #model.cache[cachekey] = data
        # </HACK: MODEL_CACHE>
        return data

    @default_method_decorator
    def _set_data(model, qtindex, value):
        """ The setter function should be of the following format def
        setter(column_name, row_id, value) column_name is the key or SQL-like
        name for the column row_id is the corresponding row key or SQL-like id
        that the row call back returned value is the value that needs to be
        stored The setter function should return a boolean, if setting the value
        was successfull or not """
        col = qtindex.column()
        row_id = model._get_row_id(qtindex)
        # <HACK: MODEL_CACHE>
        #cachekey = (row_id, col)
        #try:
        #    del model.cache[cachekey]
        #except KeyError:
        #    pass
        # </HACK: MODEL_CACHE>
        setter = model.col_setter_list[col]
        if VERBOSE:
            print('[model] Setting data: row_id=%r, setter=%r' % (row_id, setter))
        try:
            return setter(row_id, value)
        except Exception as ex:
            ut.printex(ex, 'ERROR: setting data: row_id=%r, setter=%r' % (row_id, setter))
            raise

    #------------------------
    # --- QtGui Functions ---
    #------------------------
    @default_method_decorator
    def parent(model, qindex):
        """
        A common convention used in models that expose tree data structures is
        that only items in the first column have children. For that case, when
        reimplementing this function in a subclass the column of the returned
        QModelIndex would be 0.

        When reimplementing this function in a subclass, be careful to avoid
        calling QModelIndex member functions, such as QModelIndex.parent(),
        since indexes belonging to your model will simply call your
        implementation, leading to infinite recursion.

        Returns:
            the parent of the model item with the given index. If the item has
            no parent, an invalid QModelIndex is returned.
        """

        model.lazy_checks()
        if qindex.isValid():
            node = qindex.internalPointer()
            #<HACK>
            if not isinstance(node, _atn.TreeNode):
                print("WARNING: tried to access parent of %r type object" % type(node))
                return QtCore.QModelIndex()
            #assert node.__dict__, "node.__dict__=%r" % node.__dict__
            #</HACK>
            parent_node = node.get_parent()
            parent_id = parent_node.get_id()
            if parent_id == -1 or parent_id is None:
                return QtCore.QModelIndex()
            row = parent_node.get_row()
            col = model.col_level_list.index(parent_node.get_level())
            return model.createIndex(row, col, parent_node)
        return QtCore.QModelIndex()

    @default_method_decorator
    def index(model, row, column, parent=QtCore.QModelIndex()):
        """
        Qt Override

        Returns:
            the index of the item in the model specified by the given row,
            column and parent index.  When reimplementing this function in a
            subclass, call createIndex() to generate model indexes that other
            components can use to refer to items in your model.

        NOTE:
            Object must be specified to sort delegates.
        """
        model.lazy_checks()
        if not parent.isValid():
            # This is a top level == 0 index
            #print('[model.index] ROOT: row=%r, col=%r' % (row, column))
            if row >= model.root_node.get_num_children():
                return QtCore.QModelIndex()
                #import traceback
                #traceback.print_stack()
            node = model.root_node[row]
            if model.col_level_list[column] != node.get_level():
                return QtCore.QModelIndex()
            qtindex = model.createIndex(row, column, object=node)
            return qtindex
        else:
            # This is a child level > 0 index
            parent_node = parent.internalPointer()
            node = parent_node[row]
            if ut.USE_ASSERT:
                assert isinstance(parent_node, _atn.TreeNode), type(parent_node)
                assert isinstance(node, _atn.TreeNode), type(node)
            return model.createIndex(row, column, object=node)

    def _get_level_row_count(model, qtindex):
        return model.rowCount(qtindex.parent())

    def _get_level_row_index(model, qtindex):
        node = qtindex.internalPointer()
        return node.get_row()

    @default_method_decorator
    def rowCount(model, parent=QtCore.QModelIndex()):
        """ Qt Override """
        #model.lazy_checks()
        if not parent.isValid():
            # Root row count
            if len(model.level_index_list) == 0:
                return 0
            nRows = len(model.level_index_list)
            #print('* nRows=%r' % nRows)
            return nRows
        else:
            node = parent.internalPointer()
            nRows = node.get_num_children()
            #print('+ nRows=%r' % nRows)
            return nRows

    @default_method_decorator
    def columnCount(model, parent=QtCore.QModelIndex()):
        """ Qt Override """
        # FOR NOW THE COLUMN COUNT IS CONSTANT
        model.lazy_checks()
        return len(model.col_name_list)

    @default_method_decorator
    def data(model, qtindex, role=Qt.DisplayRole, **kwargs):
        """
        Depending on the role, returns either data or how to display data
        Returns the data stored under the given role for the item referred to by
        the index.

        Note:
            If you do not have a value to return, return None
        """
        if not qtindex.isValid():
            return None
        flags = model.flags(qtindex)
        #row = qtindex.row()
        col = qtindex.column()
        node = qtindex.internalPointer()
        if model.col_level_list[col] != node.get_level():
            return QVariantHack()
        type_ = model._get_type(col)

        #if row >= model.rowCount():
        #    # Yuck.
        #    print('[item_model] Yuck. row=%r excedes rowCount=%r' %
        #          (row, model.rowCount()))
        #    return QVariantHack()

        #if role == Qt.SizeHintRole:
        #    #printDBG('REQUEST QSIZE FOR: ' + qtype.ItemDataRoles[role])
        #    return QtCore.QSize(64, 64)
        #
        # Specify Text Alignment Role
        if role == Qt.TextAlignmentRole:
            if type_ in qtype.QT_IMAGE_TYPES:
                value = Qt.AlignRight | Qt.AlignVCenter
            elif type_ in qtype.QT_BUTTON_TYPES:
                value = Qt.AlignRight | Qt.AlignVCenter
            elif type_ in ut.VALID_FLOAT_TYPES:
                value = Qt.AlignRight | Qt.AlignVCenter
            else:
                value = Qt.AlignHCenter | Qt.AlignVCenter
            return value
        #
        # Specify Background Rule
        elif role == Qt.BackgroundRole:
            value = model._get_bgrole_value(qtindex)
            if value is not None:
                return value
            if flags & Qt.ItemIsEditable:
                # Editable fields are colored
                return QVariantHack(model.EditableItemColor)
            elif flags & Qt.ItemIsUserCheckable:
                # Checkable color depends on the truth value
                data = model._get_data(qtindex, **kwargs)
                if data:
                    return QVariantHack(model.TrueItemColor)
                else:
                    return QVariantHack(model.FalseItemColor)
            else:
                pass
        #
        # Specify Foreground Role
        elif role == Qt.ForegroundRole:
            if flags & Qt.ItemIsEditable:
                return QtGui.QBrush(QtGui.QColor(0, 0, 0))

        # Specify Decoration Role (superceded by thumbdelegate)
        # elif role == Qt.DecorationRole and type_ in qtype.QT_IMAGE_TYPES:

        # Specify CheckState Role:
        if role == Qt.CheckStateRole:
            if flags & Qt.ItemIsUserCheckable:
                data = model._get_data(qtindex, **kwargs)
                return Qt.Checked if data else Qt.Unchecked
        #
        # Return the data to edit or display
        elif role in (Qt.DisplayRole, Qt.EditRole):
            # For types displayed with custom delegates do not cast data into a
            # qvariant. This includes PIXMAP, BUTTON, and COMBO
            if type_ in qtype.QT_DELEGATE_TYPES:
                data = model._get_data(qtindex, **kwargs)
                #print(data)
                return data
            else:
                # Display data with default delegate by casting to a qvariant
                data = model._get_data(qtindex, **kwargs)
                value = qtype.cast_into_qt(data)
                return value
        else:
            #import builtins
            #role_name = qtype.ItemDataRoles[role]
            #builtins.print('UNHANDLED ROLE=%r' % role_name)
            pass
        # else return None
        return QVariantHack()

    @default_method_decorator
    def setData(model, qtindex, value, role=Qt.EditRole):
        """
        Sets the role data for the item at qtindex to value.  value is a
        QVariant (called data in documentation) Returns a map with values for
        all predefined roles in the model for the item at the given index.
        Reimplement this function if you want to extend the default behavior of
        this function to include custom roles in the map.
        """
        try:
            if not qtindex.isValid():
                return None
            flags = model.flags(qtindex)
            #row = qtindex.row()
            col = qtindex.column()
            if not (flags & Qt.ItemIsEditable or flags & Qt.ItemIsUserCheckable):
                return None
            if role == Qt.CheckStateRole:
                type_ = 'QtCheckState'
                data = (value == Qt.Checked)
            elif role != Qt.EditRole:
                return False
            else:
                # Cast value into datatype
                type_ = model.col_type_list[col]
                data = qtype.cast_from_qt(value, type_)
            # Do actual setting of data
            old_data = model._get_data(qtindex)
            if old_data != data:
                model._set_data(qtindex, data)
                # This may not work with PyQt5
                # http://stackoverflow.com/questions/22560296/pyqt-list-view-not-responding-to-datachanged-signal
                # Emit that data was changed and return succcess
                model.dataChanged.emit(qtindex, qtindex)
            return True
        except Exception as ex:
            #value = str(value.toString())  # NOQA
            ut.printex(ex, 'ignoring setData', '[model]', tb=True,
                          key_list=['value'], iswarning=True)
            return False

    @default_method_decorator
    def headerData(model, section, orientation, role=Qt.DisplayRole):
        """
        Qt Override

        Returns:
            the data for the given role and section in the header with the
            specified orientation.  For horizontal headers, the section number
            corresponds to the column number. Similarly, for vertical headers,
            the section number corresponds to the row number.
        """
        model.lazy_checks()
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            column = section
            if column >= len(model.col_nice_list):
                return []
            return model.col_nice_list[column]
        #if orientation == Qt.Vertical and role == Qt.DisplayRole:
        #    row = section
        #    rowid = model._get_row_id(row)
        #    return rowid
        return QVariantHack()

    @updater
    def sort(model, column, order):
        """ Qt Override """
        model.lazy_checks()
        reverse = (order == QtCore.Qt.DescendingOrder)
        model._set_sort(column, reverse)

    @default_method_decorator
    def flags(model, qtindex):
        """
        Qt Override

        Returns:
            Qt::ItemFlag::
                 0: 'NoItemFlags'          # It does not have any properties set.
                 1: 'ItemIsSelectable'     # It can be selected.
                 2: 'ItemIsEditable'       # It can be edited.
                 4: 'ItemIsDragEnabled'    # It can be dragged.
                 8: 'ItemIsDropEnabled'    # It can be used as a drop target.
                16: 'ItemIsUserCheckable'  # It can be checked or unchecked by the user.
                32: 'ItemIsEnabled'        # The user can interact with the item.
                64: 'ItemIsTristate'       # The item is checkable with three separate states.
        """
        # Return flags based on column properties (like type, and editable)
        col      = qtindex.column()
        type_    = model._get_type(col)
        editable = model.col_edit_list[col] and model._get_level(qtindex) == model.col_level_list[col]
        if type_ in qtype.QT_IMAGE_TYPES:
            #return Qt.NoItemFlags
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable
        elif not editable:
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable
        elif type_ in ut.VALID_BOOL_TYPES:
            return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable
        else:
            return Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable
Beispiel #27
0
def to_qcolor(color):
    qcolor = QtGui.QColor(*color[0:3])
    return qcolor