Example #1
0
 def _getHeaderTitlePalette(self):
     """
     Return a palette for header title (text) label. 
     """
     palette = QPalette()
     palette.setColor(QPalette.WindowText, pmHeaderTitleColor)
     return palette
Example #2
0
 def colorframe_bgcolor_setter(color):
     #e no convenient/clean way for Formula API to permit but not require this function to receive the formula,
     # unless we store it temporarily in env._formula (which we might as well do if this feature is ever needed)
     try:
         # make sure errors here don't stop the formula from running:
         # (Need to protect against certain kinds of erroneous color values? RGBf_to_QColor does it well enough.)
         ## Qt3 code used: colorframe.setPaletteBackgroundColor(RGBf_to_QColor(color))
         qcolor = RGBf_to_QColor(color)
         palette = QPalette() # QPalette(qcolor) would have window color set from qcolor, but that doesn't help us here
         qcolorrole = QPalette.Window
             ## http://doc.trolltech.com/4.2/qpalette.html#ColorRole-enum says:
             ##   QPalette.Window    10    A general background color.
         palette.setColor(QPalette.Active, qcolorrole, qcolor) # used when window is in fg and has focus
         palette.setColor(QPalette.Inactive, qcolorrole, qcolor) # used when window is in bg or does not have focus
         palette.setColor(QPalette.Disabled, qcolorrole, qcolor) # used when widget is disabled
         colorframe.setPalette(palette)
         colorframe.setAutoFillBackground(True)
         # [Note: the above scheme was revised again by bruce 070430, for improved appearance
         #  (now has thin black border around color patch), based on Ninad's change in UserPrefs.py.]
         ## no longer needed: set color for qcolorrole = QPalette.ColorRole(role) for role in range(14)
         ## no longer needed: colorframe.setLineWidth(500) # width of outline of frame (at least half max possible size)
     except:
         print "data for following exception: ",
         print "colorframe %r has palette %r" % (colorframe, colorframe.palette())
             # fyi: in Qt4, like in Qt3, colorframe is a QFrame
         print_compact_traceback( "bug (ignored): exception in formula-setter: " ) #e include formula obj in this msg?
     pass
Example #3
0
def getPalette( palette, colorRole, color ):
    """
    Assigns a color (based on color role) to palette and returns it.
    The color/color role is assigned to all color groups.

    @param palette: A palette. If palette is None, we create and return a new
                   palette.
    @type  palette: QPalette

    @param colorRole: the Qt ColorRole
    @type  colorRole: Qt.ColorRole

    @param color: color
    @type  color: QColor

    @return: Returns the updated palette, or a new palette if none was supplied.
    @rtype : QPalette

    @see QPalette.setColor()
    """
    if palette:
        pass # Make sure palette is QPalette.
    else:
        palette = QPalette()

    palette.setColor(colorRole, color)

    return palette
Example #4
0
    def load_calibre_style(self):
        # On OS X QtCurve resets the palette, so we preserve it explicitly
        orig_pal = QPalette(self.palette())

        path = os.path.join(sys.extensions_location, 'calibre_style.'+(
            'pyd' if iswindows else 'so'))
        if not self.pi.load_style(path, 'Calibre'):
            prints('Failed to load calibre style')
        # On OSX, on some machines, colors can be invalid. See https://bugs.launchpad.net/bugs/1014900
        for role in (orig_pal.Button, orig_pal.Window):
            c = orig_pal.brush(role).color()
            if not c.isValid() or not c.toRgb().isValid():
                orig_pal.setColor(role, QColor(u'lightgray'))

        self.setPalette(orig_pal)
        style = self.style()
        icon_map = {}
        pcache = {}
        for k, v in {
            'DialogYesButton': u'ok.png',
            'DialogNoButton': u'window-close.png',
            'DialogCloseButton': u'window-close.png',
            'DialogOkButton': u'ok.png',
            'DialogCancelButton': u'window-close.png',
            'DialogHelpButton': u'help.png',
            'DialogOpenButton': u'document_open.png',
            'DialogSaveButton': u'save.png',
            'DialogApplyButton': u'ok.png',
            'DialogDiscardButton': u'trash.png',
            'MessageBoxInformation': u'dialog_information.png',
            'MessageBoxWarning': u'dialog_warning.png',
            'MessageBoxCritical': u'dialog_error.png',
            'MessageBoxQuestion': u'dialog_question.png',
            'BrowserReload': u'view-refresh.png',
            # These two are used to calculate the sizes for the doc widget
            # title bar buttons, therefore, they have to exist. The actual
            # icon is not used.
            'TitleBarCloseButton': u'window-close.png',
            'TitleBarNormalButton': u'window-close.png',
            'DockWidgetCloseButton': u'window-close.png',
        }.iteritems():
            if v not in pcache:
                p = I(v)
                if isinstance(p, bytes):
                    p = p.decode(filesystem_encoding)
                # if not os.path.exists(p): raise ValueError(p)
                pcache[v] = p
            v = pcache[v]
            icon_map[type('')(getattr(style, 'SP_'+k))] = v
        style.setProperty(u'calibre_icon_map', icon_map)
        self.__icon_map_memory_ = icon_map
    def _set_widget_erase_color(self): # revised, bruce 071011
        """
        Change this widget's erase color (seen only if it's resized,
        and only briefly -- it's independent of OpenGL clearColor) to
        self.backgroundColor. This is intended to minimize the visual
        effect of widget resizes which temporarily show the erase
        color. See comments in this method for caveats about that.
        """
        # Note: this was called in GLPane.update_after_new_graphicsMode
        # when the graphicsMode could determine the background color,
        # but that's no longer true, so it could probably
        # just be called at startup and whenever the background color is changed.
        # Try that sometime, it might be an optim. For now it continues
        # to be called from there. [bruce 071011, still true 080910]
        #
        # REVIEW: what is self.backgroundColor when we're using the new default
        # of "Blue Sky Gradient". For best effect here, what it ought to be
        # is the average or central bg color in that gradient. I think it's not,
        # which makes me wonder if this bugfix is still needed at all. [bruce 071011]
        #
        # Note: calling this fixed the bug in which the glpane or its edges
        # flickered to black during a main-window resize. [bruce 050408]
        #
        # Note: limited this to Mac [in caller], since it turns out that bug (which has
        # no bug number yet) was Mac-specific, but this change caused a new bug 530
        # on Windows. (Not sure about Linux.) See also bug 141 (black during
        # mode-change), related but different. [bruce 050413]
        #
        # Note: for graphicsModes with a translucent surface covering the screen
        # (i.e. Build Atoms water surface), it would be better to blend that surface
        # color with self.backgroundColor for passing to this method, to approximate
        # the effective background color. Alternatively, we could change how those
        # graphicsModes set up OpenGL clearcolor, so that their empty space areas
        # looked like self.backgroundColor.) [bruce 050615 comment]

        bgcolor = self.backgroundColor
        r = int(bgcolor[0]*255 + 0.5) # (same formula as in elementSelector.py)
        g = int(bgcolor[1]*255 + 0.5)
        b = int(bgcolor[2]*255 + 0.5)
        pal = QPalette()
        pal.setColor(self.backgroundRole(), QColor(r, g, b))
        self.setPalette(pal)
            # see Qt docs for this and for backgroundRole
        return
    def _initialize_collections(self):
        '''
        Populate the data model with current collection assignments
        Hook click, doubleClick events
        '''
        self._log_location()

        # Set the bg color of the description text fields to the dialog bg color
        if False:
            bgcolor = self.palette().color(QPalette.Background)
            palette = QPalette()
            palette.setColor(QPalette.Base, bgcolor)
            self.calibre_lw.setPalette(palette)
            self.marvin_lw.setPalette(palette)

        if self.calibre_collections is not None:
            for ca in self.calibre_collections:
                item = ListWidgetItem(ca)
                item.setData(Qt.UserRole, ca)
                if RENAMING_ENABLED:
                    item.setFlags(item.flags() | Qt.ItemIsEditable)
                self.calibre_lw.addItem(item)

        for ma in self.marvin_collections:
            item = ListWidgetItem(ma)
            item.setData(Qt.UserRole, ma)
            if RENAMING_ENABLED:
                item.setFlags(item.flags() | Qt.ItemIsEditable)
            self.marvin_lw.addItem(item)

        # Capture click events to clear selections in opposite list
        self.calibre_lw.clicked.connect(self._clear_marvin_selection)
        self.marvin_lw.clicked.connect(self._clear_calibre_selection)

        # Hook double-click events
        if RENAMING_ENABLED:
            self.calibre_lw.doubleClicked.connect(self.rename_calibre_tag)
            self.marvin_lw.doubleClicked.connect(self.rename_marvin_tag)

        # Enable sorting
        if self.calibre_collections is not None:
            self.calibre_lw.setSortingEnabled(True)
        self.marvin_lw.setSortingEnabled(True)
 def setup_inconsistency_checking(self):
     # set-up inconsistency label
     inconsistency_palette = QPalette()
     inconsistency_palette.setColor(QPalette.WindowText, Qt.red)
     self.inconsistencyLabel.setPalette(inconsistency_palette)
     self.inconsistencyLabel.setVisible(False)
     
     def action_consistent_table():    
         self.inconsistencyLabel.setVisible(False)
         self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
     def action_inconsistent_table():
         # show label, disable OK buttonbox button
         self.inconsistencyLabel.setVisible(True)
         self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
     
     self.check_table_consistency = meta_globals.ConsistencyChecker(
                         fn_consistent=action_consistent_table,
                         fn_inconsistent=action_inconsistent_table,
                         table_2x2=self.raw_data_table)
Example #8
0
    def _createHeader(self, iconPath, title):
        """
        Creates the Property Manager header, which contains an icon
        (a QLabel with a pixmap) and white text (a QLabel with text).
        
        @param iconPath: The relative path for the icon (PNG image) that 
                         appears in the header.
        @type  iconPath: str
        
        @param title: The title that appears in the header.
        @type  title: str
        """

        # Heading frame (dark gray), which contains
        # a pixmap and (white) heading text.
        self.headerFrame = QFrame(self)
        self.headerFrame.setFrameShape(QFrame.NoFrame)
        self.headerFrame.setFrameShadow(QFrame.Plain)

        self.headerFrame.setPalette(QPalette(pmHeaderFrameColor))
        self.headerFrame.setAutoFillBackground(True)

        # HBox layout for heading frame, containing the pixmap
        # and label (title).
        HeaderFrameHLayout = QHBoxLayout(self.headerFrame)
        # 2 pixels around edges --
        HeaderFrameHLayout.setMargin(PM_HEADER_FRAME_MARGIN)
        # 5 pixel between pixmap and label. --
        HeaderFrameHLayout.setSpacing(PM_HEADER_FRAME_SPACING)

        # PropMgr icon. Set image by calling setHeaderIcon().
        self.headerIcon = QLabel(self.headerFrame)
        self.headerIcon.setSizePolicy(
            QSizePolicy(QSizePolicy.Policy(QSizePolicy.Fixed),
                        QSizePolicy.Policy(QSizePolicy.Fixed)))

        self.headerIcon.setScaledContents(True)

        HeaderFrameHLayout.addWidget(self.headerIcon)

        # PropMgr header title text (a QLabel).
        self.headerTitle = QLabel(self.headerFrame)
        headerTitlePalette = self._getHeaderTitlePalette()
        self.headerTitle.setPalette(headerTitlePalette)
        self.headerTitle.setAlignment(PM_LABEL_LEFT_ALIGNMENT)

        # Assign header title font.
        self.headerTitle.setFont(self._getHeaderFont())
        HeaderFrameHLayout.addWidget(self.headerTitle)

        self.vBoxLayout.addWidget(self.headerFrame)

        # Set header icon and title text.
        self.setHeaderIcon(iconPath)
        self.setHeaderTitle(title)
Example #9
0
    def __init__(self, name, iconPath="", title=""):
        """
        Property Manager constructor.
        
        @param name: the name to assign the property manager dialog object.
        @type  name: str
        
        @param iconPath: the relative path for the icon (PNG image) that 
                         appears in the header.
        @type  iconPath: str
        
        @param title: the title that appears in the header.
        @type  title: str
        """

        QDialog.__init__(self)

        self.setObjectName(name)
        self._widgetList = []

        # Main pallete for PropMgr.

        self.setPalette(QPalette(pmColor))

        # Main vertical layout for PropMgr.
        self.vBoxLayout = QVBoxLayout(self)
        self.vBoxLayout.setMargin(PM_MAINVBOXLAYOUT_MARGIN)
        self.vBoxLayout.setSpacing(PM_MAINVBOXLAYOUT_SPACING)

        # Add PropMgr's header, sponsor button, top row buttons and (hidden)
        # message group box.
        self._createHeader(iconPath, title)
        self._createSponsorButton()
        self._createTopRowBtns()  # Create top buttons row

        self.MessageGroupBox = PM_MessageGroupBox(self)

        # Keep the line below around; it might be useful.
        # I may want to use it now that I understand it.
        # Mark 2007-05-17.
        #QMetaObject.connectSlotsByName(self)

        self._addGroupBoxes()

        try:
            self._addWhatsThisText()
        except:
            print_compact_traceback("Error loading whatsthis text for this " \
                                    "property manager.")

        try:
            self._addToolTipText()
        except:
            print_compact_traceback("Error loading tool tip text for this " \
                                    "property manager.")
Example #10
0
 def set_color(self):
     r, g, b = gprefs['cover_grid_color']
     pal = QPalette()
     col = QColor(r, g, b)
     pal.setColor(pal.Base, col)
     dark = (r + g + b) / 3.0 < 128
     pal.setColor(pal.Text, QColor(Qt.white if dark else Qt.black))
     self.setPalette(pal)
     self.delegate.highlight_color = pal.color(pal.Text)
 def _updateColorFrame(self):
     """
     Updates the color frame with the current color.
     """
     colorframe = self.colorFrame
     try:
         qcolor = self.getQColor()
         palette = QPalette() # QPalette(qcolor) would have window color set from qcolor, but that doesn't help us here
         qcolorrole = QPalette.Window
             ## http://doc.trolltech.com/4.2/qpalette.html#ColorRole-enum says:
             ##   QPalette.Window    10    A general background color.
         palette.setColor(QPalette.Active, qcolorrole, qcolor) # used when window is in fg and has focus
         palette.setColor(QPalette.Inactive, qcolorrole, qcolor) # used when window is in bg or does not have focus
         palette.setColor(QPalette.Disabled, qcolorrole, qcolor) # used when widget is disabled
         colorframe.setPalette(palette)
         colorframe.setAutoFillBackground(True)
     except:
         print "data for following exception: ",
         print "colorframe %r has palette %r" % (colorframe, colorframe.palette())
     pass
    def _populate_description(self):
        # Set the bg color of the description text fields to the dialog bg color
        bgcolor = self.palette().color(QPalette.Background)
        palette = QPalette()
        palette.setColor(QPalette.Base, bgcolor)
        self.calibre_description.setPalette(palette)
        self.marvin_description.setPalette(palette)

        if 'comments' in self.mismatches:
            self.calibre_description_label.setText(self.YELLOW_BG.format("<b>Description</b>"))
            if self.mismatches['comments']['calibre']:
                self.calibre_description.setText(self.mismatches['comments']['calibre'])

            self.marvin_description_label.setText(self.YELLOW_BG.format("<b>Description</b>"))
            if self.mismatches['comments']['Marvin']:
                self.marvin_description.setText(self.mismatches['comments']['Marvin'])
        else:
            if self.installed_book.comments:
                self.calibre_description.setText(self.installed_book.comments)
                self.marvin_description.setText(self.installed_book.comments)
Example #13
0
 def set_color(self):
     r, g, b = gprefs['cover_grid_color']
     pal = QPalette()
     col = QColor(r, g, b)
     pal.setColor(pal.Base, col)
     tex = gprefs['cover_grid_texture']
     if tex:
         from calibre.gui2.preferences.texture_chooser import texture_path
         path = texture_path(tex)
         if path:
             pal.setBrush(pal.Base, QBrush(QPixmap(path)))
     dark = (r + g + b)/3.0 < 128
     pal.setColor(pal.Text, QColor(Qt.white if dark else Qt.black))
     self.setPalette(pal)
     self.delegate.highlight_color = pal.color(pal.Text)
Example #14
0
 def set_color(self):
     r, g, b = gprefs['cover_grid_color']
     pal = QPalette()
     col = QColor(r, g, b)
     pal.setColor(pal.Base, col)
     tex = gprefs['cover_grid_texture']
     if tex:
         from calibre.gui2.preferences.texture_chooser import texture_path
         path = texture_path(tex)
         if path:
             pm = QPixmap(path)
             if not pm.isNull():
                 val = pm.scaled(1, 1).toImage().pixel(0, 0)
                 r, g, b = qRed(val), qGreen(val), qBlue(val)
                 pal.setBrush(pal.Base, QBrush(pm))
     dark = (r + g + b) / 3.0 < 128
     pal.setColor(pal.Text, QColor(Qt.white if dark else Qt.black))
     self.setPalette(pal)
     self.delegate.highlight_color = pal.color(pal.Text)
Example #15
0
 def set_color(self):
     r, g, b = gprefs['cover_grid_color']
     pal = QPalette()
     col = QColor(r, g, b)
     pal.setColor(pal.Base, col)
     dark = (r + g + b)/3.0 < 128
     pal.setColor(pal.Text, QColor(Qt.white if dark else Qt.black))
     self.setPalette(pal)
     self.delegate.highlight_color = pal.color(pal.Text)
Example #16
0
    def __init__(self,
            prompt='>>> ',
            continuation='... ',
            parent=None):
        QTextEdit.__init__(self, parent)
        self.shutting_down = False
        self.compiler = CommandCompiler()
        self.buf = self.old_buf = []
        self.history = History([''], dynamic.get('console_history', []))
        self.prompt_frame = None
        self.allow_output = False
        self.prompt_frame_format = QTextFrameFormat()
        self.prompt_frame_format.setBorder(1)
        self.prompt_frame_format.setBorderStyle(QTextFrameFormat.BorderStyle_Solid)
        self.prompt_len = len(prompt)

        self.doc.setMaximumBlockCount(int(prefs['scrollback']))
        self.lexer = PythonLexer(ensurenl=False)
        self.tb_lexer = PythonTracebackLexer()

        self.context_menu = cm = QMenu(self) # {{{
        cm.theme = ThemeMenu(cm)
        # }}}

        self.formatter = Formatter(prompt, continuation, style=prefs['theme'])
        p = QPalette()
        p.setColor(p.Base, QColor(self.formatter.background_color))
        p.setColor(p.Text, QColor(self.formatter.color))
        self.setPalette(p)

        self.key_dispatcher = { # {{{
                Qt.Key_Enter : self.enter_pressed,
                Qt.Key_Return : self.enter_pressed,
                Qt.Key_Up : self.up_pressed,
                Qt.Key_Down : self.down_pressed,
                Qt.Key_Home : self.home_pressed,
                Qt.Key_End : self.end_pressed,
                Qt.Key_Left : self.left_pressed,
                Qt.Key_Right : self.right_pressed,
                Qt.Key_Backspace : self.backspace_pressed,
                Qt.Key_Delete : self.delete_pressed,
        } # }}}

        motd = textwrap.dedent('''\
        # Python {0}
        # {1} {2}
        '''.format(sys.version.splitlines()[0], __appname__,
            __version__))

        sys.excepthook = self.unhandled_exception

        self.controllers = []
        QTimer.singleShot(0, self.launch_controller)


        with EditBlock(self.cursor):
            self.render_block(motd)
Example #17
0
    def _populate_description(self):
        # Set the bg color of the description text fields to the dialog bg color
        bgcolor = self.palette().color(QPalette.Background)
        palette = QPalette()
        palette.setColor(QPalette.Base, bgcolor)
        self.calibre_description.setPalette(palette)
        self.marvin_description.setPalette(palette)

        if 'comments' in self.mismatches:
            self.calibre_description_label.setText(
                self.YELLOW_BG.format("<b>Description</b>"))
            if self.mismatches['comments']['calibre']:
                self.calibre_description.setText(
                    self.mismatches['comments']['calibre'])

            self.marvin_description_label.setText(
                self.YELLOW_BG.format("<b>Description</b>"))
            if self.mismatches['comments']['Marvin']:
                self.marvin_description.setText(
                    self.mismatches['comments']['Marvin'])
        else:
            if self.installed_book.comments:
                self.calibre_description.setText(self.installed_book.comments)
                self.marvin_description.setText(self.installed_book.comments)
Example #18
0
 def set_color(self):
     r, g, b = gprefs['cover_grid_color']
     pal = QPalette()
     col = QColor(r, g, b)
     pal.setColor(pal.Base, col)
     tex = gprefs['cover_grid_texture']
     if tex:
         from calibre.gui2.preferences.texture_chooser import texture_path
         path = texture_path(tex)
         if path:
             pm = QPixmap(path)
             if not pm.isNull():
                 val = pm.scaled(1, 1).toImage().pixel(0, 0)
                 r, g, b = qRed(val), qGreen(val), qBlue(val)
                 pal.setBrush(pal.Base, QBrush(pm))
     dark = (r + g + b)/3.0 < 128
     pal.setColor(pal.Text, QColor(Qt.white if dark else Qt.black))
     self.setPalette(pal)
     self.delegate.highlight_color = pal.color(pal.Text)
    def __init__(self, ma_unit, cur_txs, cur_group_str, parent=None):
        super(DiagnosticDataForm, self).__init__(parent)
        self.setupUi(self)
        self.setup_signals_and_slots()
        self.ma_unit = ma_unit
        self.raw_data_dict = {}
        for group in cur_txs:
            raw_data = self.ma_unit.get_raw_data_for_group(group)
            self.raw_data_dict[group] = raw_data
        self.cur_groups = cur_txs
        self.group_str = cur_group_str
        self.cur_effect = "Sens" # arbitrary
        
        self.entry_widgets = [self.two_by_two_table, self.prevalence_txt_box,
                              self.low_txt_box, self.high_txt_box,
                              self.effect_txt_box,]
        self.already_showed_change_CI_alert = False
        
        # block all the widgets for a moment
        self.block_all_signals(True)
        
        meta_globals.init_ci_spinbox_and_label(self.CI_spinbox, self.ci_label)
        
        self.setup_inconsistency_checking()
        self.initialize_backup_structures()
        self.setup_clear_button_palettes()
        
        self.setup_table_effect_dict()         # gather effect info from ma_unit
        self._read_in_table_data_from_MAunit() # populate table items from raw data in ma_unit
        self._populate_effect_cmbo_box()     # make cmbo box entries for effects
        self._update_data_table()         # fill in the rest of the data table
        self.set_current_effect()         # fill in current effect data in line edits
        self.enable_back_calculation_btn()
        self.enable_txt_box_input()
        self.save_form_state()

        # unblock
        self.block_all_signals(False)
        
        # Color for clear_button_pallette
        self.orig_palette = self.clear_Btn.palette()
        self.pushme_palette = QPalette()
        self.pushme_palette.setColor(QPalette.ButtonText,Qt.red)
        self.set_clear_btn_color()
Example #20
0
 def _updateColorFrame(self):
     """
     Updates the color frame with the current color.
     """
     colorframe = self.colorFrame
     try:
         qcolor = self.getQColor()
         palette = QPalette() # QPalette(qcolor) would have window color set from qcolor, but that doesn't help us here
         qcolorrole = QPalette.Window
             ## http://doc.trolltech.com/4.2/qpalette.html#ColorRole-enum says:
             ##   QPalette.Window    10    A general background color.
         palette.setColor(QPalette.Active, qcolorrole, qcolor) # used when window is in fg and has focus
         palette.setColor(QPalette.Inactive, qcolorrole, qcolor) # used when window is in bg or does not have focus
         palette.setColor(QPalette.Disabled, qcolorrole, qcolor) # used when widget is disabled
         colorframe.setPalette(palette)
         colorframe.setAutoFillBackground(True)
     except:
         print "data for following exception: ",
         print "colorframe %r has palette %r" % (colorframe, colorframe.palette())
     pass
Example #21
0
 def set_cg_color(self, val):
     pal = QPalette()
     pal.setColor(QPalette.Window, QColor(*val))
     self.cover_grid_color_label.setPalette(pal)
    def initialize(self, parent, book_id, cid, installed_book, enable_metadata_updates, marvin_db_path):
        '''
        __init__ is called on SizePersistedDialog()
        shared attributes of interest:
            .authors
            .author_sort
            .cover_hash
            .pubdate
            .publisher
            .rating
            .series
            .series_index
            .title
            .title_sort
            .comments
            .tags
            .uuid
        '''
        self.setupUi(self)
        self.book_id = book_id
        self.cid = cid
        self.connected_device = parent.opts.gui.device_manager.device
        self.installed_book = installed_book
        self.marvin_db_path = marvin_db_path
        self.opts = parent.opts
        self.parent = parent
        self.stored_command = None
        self.verbose = parent.verbose
        self.BORDER_LR = 4
        self.BORDER_TB = 8
        self.GREY_FG = '<font style="color:#A0A0A0">{0}</font>'
        self.YELLOW_BG = '<font style="background:#FDFF99">{0}</font>'

        self._log_location(installed_book.title)

        # Subscribe to Marvin driver change events
        self.connected_device.marvin_device_signals.reader_app_status_changed.connect(
            self.marvin_status_changed)

        #self._log("mismatches:\n%s" % repr(installed_book.metadata_mismatches))
        self.mismatches = installed_book.metadata_mismatches

        self._populate_title()
        self._populate_title_sort()
        self._populate_series()
        self._populate_authors()
        self._populate_author_sort()
        self._populate_uuid()
        self._populate_covers()
        self._populate_subjects()
        self._populate_publisher()
        self._populate_pubdate()
        self._populate_rating()
        self._populate_description()

        # ~~~~~~~~ Export to Marvin button ~~~~~~~~
        self.export_to_marvin_button.setIcon(QIcon(os.path.join(self.parent.opts.resources_path,
                                                   'icons',
                                                   'from_calibre.png')))
        self.export_to_marvin_button.clicked.connect(partial(self.store_command, 'export_metadata'))
        self.export_to_marvin_button.setEnabled(enable_metadata_updates)

        # ~~~~~~~~ Import from Marvin button ~~~~~~~~
        self.import_from_marvin_button.setIcon(QIcon(os.path.join(self.parent.opts.resources_path,
                                                     'icons',
                                                     'from_marvin.png')))
        self.import_from_marvin_button.clicked.connect(partial(self.store_command, 'import_metadata'))
        self.import_from_marvin_button.setEnabled(enable_metadata_updates)

        # If no calibre book, or no mismatches, adjust the display accordingly
        if not self.cid:
            #self._log("self.cid: %s" % repr(self.cid))
            #self._log("self.mismatches: %s" % repr(self.mismatches))
            self.calibre_gb.setVisible(False)
            self.import_from_marvin_button.setVisible(False)
            self.setWindowTitle(u'Marvin metadata')
        elif not self.mismatches:
            # Show both panels, but hide the transfer buttons
            self.export_to_marvin_button.setVisible(False)
            self.import_from_marvin_button.setVisible(False)
        else:
            self.setWindowTitle(u'Metadata Summary')

        if False:
            # Set the Marvin QGroupBox to Marvin red
            marvin_red = QColor()
            marvin_red.setRgb(189, 17, 20, alpha=255)
            palette = QPalette()
            palette.setColor(QPalette.Background, marvin_red)
            self.marvin_gb.setPalette(palette)

        # ~~~~~~~~ Add a Close or Cancel button ~~~~~~~~
        self.close_button = QPushButton(QIcon(I('window-close.png')), 'Close')
        if self.mismatches:
            self.close_button.setText('Cancel')
        self.bb.addButton(self.close_button, QDialogButtonBox.RejectRole)

        self.bb.clicked.connect(self.dispatch_button_click)

        # Restore position
        self.resize_dialog()
Example #23
0
    def initGraphics(self):

        # LED color palettes
        self.green_palette = QPalette()
        self.green_palette.setColor(QPalette.Window, QColor(0, 255, 0))

        self.red_palette = QPalette()
        self.red_palette.setColor(QPalette.Window, QColor(255, 0, 0))

        self.yellow_palette = QPalette()
        self.yellow_palette.setColor(QPalette.Window, QColor(200, 200, 50))

        self.gray_palette = QPalette()
        self.gray_palette.setColor(QPalette.Window, QColor(80, 80, 80))

        # CAN RX LEDs
        self._widget.throttle_led.setText('')
        self._widget.throttle_led.setPalette(self.red_palette)
        self._widget.brake_led.setText('')
        self._widget.brake_led.setPalette(self.red_palette)
        self._widget.steering_led.setText('')
        self._widget.steering_led.setPalette(self.red_palette)
        self._widget.gear_led.setText('')
        self._widget.gear_led.setPalette(self.red_palette)

        # BOO LED
        self._widget.boo_led.setText('')
        self._widget.boo_led.setPalette(self.gray_palette)

        # Fault and driver override LEDs
        self._widget.throttle_driver_led.setText('')
        self._widget.throttle_driver_led.setPalette(self.gray_palette)
        self._widget.throttle_flt1_led.setText('')
        self._widget.throttle_flt1_led.setPalette(self.gray_palette)
        self._widget.throttle_flt2_led.setText('')
        self._widget.throttle_flt2_led.setPalette(self.gray_palette)
        self._widget.throttle_fltcon_led.setText('')
        self._widget.throttle_fltcon_led.setPalette(self.gray_palette)

        self._widget.brake_driver_led.setText('')
        self._widget.brake_driver_led.setPalette(self.gray_palette)
        self._widget.brake_flt1_led.setText('')
        self._widget.brake_flt1_led.setPalette(self.gray_palette)
        self._widget.brake_flt2_led.setText('')
        self._widget.brake_flt2_led.setPalette(self.gray_palette)
        self._widget.brake_fltcon_led.setText('')
        self._widget.brake_fltcon_led.setPalette(self.gray_palette)
        self._widget.brake_fltb_led.setText('')
        self._widget.brake_fltb_led.setPalette(self.gray_palette)

        self._widget.steering_driver_led.setText('')
        self._widget.steering_flt1_led.setText('')
        self._widget.steering_flt2_led.setText('')
        self._widget.steering_fltcon_led.setText('')

        self._widget.gear_driver_led.setText('')
        self._widget.gear_fltbus_led.setText('')

        # Steering wheel buttons
        self._widget.on_off_led.setText('')
        self._widget.on_off_led.setPalette(self.gray_palette)
        self._widget.res_cncl_led.setText('')
        self._widget.res_cncl_led.setPalette(self.gray_palette)
        self._widget.set_inc_led.setText('')
        self._widget.set_inc_led.setPalette(self.gray_palette)
        self._widget.set_dec_led.setText('')
        self._widget.set_dec_led.setPalette(self.gray_palette)
        self._widget.gap_inc_led.setText('')
        self._widget.gap_inc_led.setPalette(self.gray_palette)
        self._widget.gap_dec_led.setText('')
        self._widget.gap_dec_led.setPalette(self.gray_palette)
        self._widget.la_on_off_led.setText('')
        self._widget.la_on_off_led.setPalette(self.gray_palette)
Example #24
0
class MkzGui(Plugin):

    package_name = 'dbw_mkz_gui'  # Name of ROS package
    ui_filename = 'dbw_mkz_gui.ui'  # filename of the QT gui resource
    gui_object_name = 'MkzGui'  # runtime name of the GUI plugin
    update_period = 100  # GUI update period in ms

    def __init__(self, context):
        self.initVariables()
        self.setupWidget(context)
        self.initGraphics()
        self.bindCallbacks()
        self.subscribeTopics()
        self.advertiseTopics()

    def initVariables(self):
        self.rad_to_deg = 57.295779515

        # DBW reported values
        self.reported_throttle = 0
        self.reported_brake = 0
        self.reported_boo = False
        self.reported_steering = 0
        self.reported_gear = '--'

        # DBW commands
        self.throttle_cmd = 0
        self.brake_cmd = 0
        self.steering_cmd = 0

        # Steering wheel button states
        self.on_off_btn = False
        self.res_cncl_btn = False
        self.set_inc_btn = False
        self.set_dec_btn = False
        self.gap_inc_btn = False
        self.gap_dec_btn = False
        self.la_on_off_btn = False

        # Message RX status
        self.throttle_stamp = rospy.Time()
        self.brake_stamp = rospy.Time()
        self.steering_stamp = rospy.Time()
        self.gear_stamp = rospy.Time()
        self.misc_stamp = rospy.Time()

        # Vehicle data labels
        self.gps_lat = 0
        self.gps_lon = 0
        self.speed = 0
        self.fl_tire = 0
        self.fr_tire = 0
        self.rl_tire = 0
        self.rr_tire = 0
        self.yaw_rate = 0
        self.roll_rate = 0
        self.fuel = 0

        # Report gear name map
        self.gear_map = []
        self.gear_map.append('None')
        self.gear_map.append('Park')
        self.gear_map.append('Reverse')
        self.gear_map.append('Neutral')
        self.gear_map.append('Drive')
        self.gear_map.append('Low')

        # Throttle faults
        self.throttle_driver = False
        self.throttle_flt1 = False
        self.throttle_flt2 = False
        self.throttle_fltcon = False

        # Brake faults
        self.brake_driver = False
        self.brake_flt1 = False
        self.brake_flt2 = False
        self.brake_fltboo = False
        self.brake_fltcon = False

        # Steering faults
        self.steering_driver = False
        self.steering_flt1 = False
        self.steering_flt2 = False
        self.steering_fltcon = False

        # Gear faults
        self.gear_driver = False
        self.gear_fltbus = False

    def updateGuiCallback(self):
        current_time = rospy.Time.now()

        # DBW system commands and reports
        self._widget.throttle_report_lbl.setText(str(self.reported_throttle))
        self._widget.brake_report_lbl.setText(str(self.reported_brake))
        self._widget.steering_report_lbl.setText(str(self.reported_steering))
        self._widget.gear_report_lbl.setText(self.reported_gear)

        self._widget.throttle_cmd_lbl.setText(str(self.throttle_cmd))
        self._widget.brake_cmd_lbl.setText(str(self.brake_cmd))
        self._widget.steering_cmd_lbl.setText(str(self.steering_cmd))

        # Steering wheel buttons
        if (current_time - self.misc_stamp) < rospy.Duration(0.25):
            if self.res_cncl_btn:
                self._widget.res_cncl_led.setPalette(self.green_palette)
            else:
                self._widget.res_cncl_led.setPalette(self.red_palette)

            if self.on_off_btn:
                self._widget.on_off_led.setPalette(self.green_palette)
            else:
                self._widget.on_off_led.setPalette(self.red_palette)

            if self.set_inc_btn:
                self._widget.set_inc_led.setPalette(self.green_palette)
            else:
                self._widget.set_inc_led.setPalette(self.red_palette)

            if self.set_dec_btn:
                self._widget.set_dec_led.setPalette(self.green_palette)
            else:
                self._widget.set_dec_led.setPalette(self.red_palette)

            if self.gap_inc_btn:
                self._widget.gap_inc_led.setPalette(self.green_palette)
            else:
                self._widget.gap_inc_led.setPalette(self.red_palette)

            if self.gap_dec_btn:
                self._widget.gap_dec_led.setPalette(self.green_palette)
            else:
                self._widget.gap_dec_led.setPalette(self.red_palette)

            if self.la_on_off_btn:
                self._widget.la_on_off_led.setPalette(self.green_palette)
            else:
                self._widget.la_on_off_led.setPalette(self.red_palette)
        else:
            self._widget.on_off_led.setPalette(self.gray_palette)
            self._widget.res_cncl_led.setPalette(self.gray_palette)
            self._widget.set_inc_led.setPalette(self.gray_palette)
            self._widget.set_dec_led.setPalette(self.gray_palette)
            self._widget.gap_inc_led.setPalette(self.gray_palette)
            self._widget.gap_dec_led.setPalette(self.gray_palette)
            self._widget.la_on_off_led.setPalette(self.gray_palette)

        # Report RX status LEDs
        if (current_time - self.throttle_stamp) < rospy.Duration(0.25):
            self._widget.throttle_led.setPalette(self.green_palette)
        else:
            self._widget.throttle_led.setPalette(self.red_palette)

        if (current_time - self.brake_stamp) < rospy.Duration(0.25):
            self._widget.brake_led.setPalette(self.green_palette)
        else:
            self._widget.brake_led.setPalette(self.red_palette)

        if (current_time - self.steering_stamp) < rospy.Duration(0.25):
            self._widget.steering_led.setPalette(self.green_palette)
        else:
            self._widget.steering_led.setPalette(self.red_palette)

        if (current_time - self.gear_stamp) < rospy.Duration(0.25):
            self._widget.gear_led.setPalette(self.green_palette)
        else:
            self._widget.gear_led.setPalette(self.red_palette)

        # Throttle faults
        if (current_time - self.throttle_stamp) < rospy.Duration(0.25):
            if self.throttle_driver:
                self._widget.throttle_driver_led.setPalette(
                    self.yellow_palette)
            else:
                self._widget.throttle_driver_led.setPalette(self.green_palette)

            if self.throttle_flt1:
                self._widget.throttle_flt1_led.setPalette(self.red_palette)
            else:
                self._widget.throttle_flt1_led.setPalette(self.green_palette)

            if self.throttle_flt2:
                self._widget.throttle_flt2_led.setPalette(self.red_palette)
            else:
                self._widget.throttle_flt2_led.setPalette(self.green_palette)

            if self.throttle_fltcon:
                self._widget.throttle_fltcon_led.setPalette(self.red_palette)
            else:
                self._widget.throttle_fltcon_led.setPalette(self.green_palette)
        else:
            self._widget.throttle_driver_led.setPalette(self.gray_palette)
            self._widget.throttle_flt1_led.setPalette(self.gray_palette)
            self._widget.throttle_flt2_led.setPalette(self.gray_palette)
            self._widget.throttle_fltcon_led.setPalette(self.gray_palette)

        # Brake faults
        if (current_time - self.brake_stamp) < rospy.Duration(0.25):
            if self.brake_driver:
                self._widget.brake_driver_led.setPalette(self.yellow_palette)
            else:
                self._widget.brake_driver_led.setPalette(self.green_palette)

            if self.brake_flt1:
                self._widget.brake_flt1_led.setPalette(self.red_palette)
            else:
                self._widget.brake_flt1_led.setPalette(self.green_palette)

            if self.brake_flt2:
                self._widget.brake_flt2_led.setPalette(self.red_palette)
            else:
                self._widget.brake_flt2_led.setPalette(self.green_palette)

            if self.brake_fltcon:
                self._widget.brake_fltcon_led.setPalette(self.red_palette)
            else:
                self._widget.brake_fltcon_led.setPalette(self.green_palette)

            if self.brake_fltboo:
                self._widget.brake_fltb_led.setPalette(self.red_palette)
            else:
                self._widget.brake_fltb_led.setPalette(self.green_palette)
        else:
            self._widget.brake_driver_led.setPalette(self.gray_palette)
            self._widget.brake_flt1_led.setPalette(self.gray_palette)
            self._widget.brake_flt2_led.setPalette(self.gray_palette)
            self._widget.brake_fltcon_led.setPalette(self.gray_palette)
            self._widget.brake_fltb_led.setPalette(self.gray_palette)

        # Steering faults
        if (current_time - self.steering_stamp) < rospy.Duration(0.25):
            if self.steering_driver:
                self._widget.steering_driver_led.setPalette(
                    self.yellow_palette)
            else:
                self._widget.steering_driver_led.setPalette(self.green_palette)

            if self.steering_flt1:
                self._widget.steering_flt1_led.setPalette(self.red_palette)
            else:
                self._widget.steering_flt1_led.setPalette(self.green_palette)

            if self.steering_flt2:
                self._widget.steering_flt2_led.setPalette(self.red_palette)
            else:
                self._widget.steering_flt2_led.setPalette(self.green_palette)

            if self.steering_fltcon:
                self._widget.steering_fltcon_led.setPalette(self.red_palette)
            else:
                self._widget.steering_flt2_led.setPalette(self.green_palette)
        else:
            self._widget.steering_driver_led.setPalette(self.gray_palette)
            self._widget.steering_flt1_led.setPalette(self.gray_palette)
            self._widget.steering_flt2_led.setPalette(self.gray_palette)
            self._widget.steering_fltcon_led.setPalette(self.gray_palette)

        # Gear faults
        if (current_time - self.gear_stamp) < rospy.Duration(0.25):
            if self.gear_driver:
                self._widget.gear_driver_led.setPalette(self.yellow_palette)
            else:
                self._widget.gear_driver_led.setPalette(self.green_palette)

            if self.gear_fltbus:
                self._widget.gear_fltbus_led.setPalette(self.red_palette)
            else:
                self._widget.gear_fltbus_led.setPalette(self.green_palette)
        else:
            self._widget.gear_driver_led.setPalette(self.gray_palette)
            self._widget.gear_fltbus_led.setPalette(self.gray_palette)

        # Vehicle data labels
        self._widget.lat_lbl.setText(str(self.gps_lat))
        self._widget.lon_lbl.setText(str(self.gps_lon))
        self._widget.speed_lbl.setText(str(self.speed) + ' m/s')
        self._widget.fl_pressure_lbl.setText(str(self.fl_tire))
        self._widget.fr_pressure_lbl.setText(str(self.fr_tire))
        self._widget.rl_pressure_lbl.setText(str(self.rl_tire))
        self._widget.rr_pressure_lbl.setText(str(self.rr_tire))
        self._widget.yaw_rate_lbl.setText(str(self.yaw_rate) + ' rad/s')
        self._widget.roll_rate_lbl.setText(str(self.roll_rate) + ' rad/s')
        self._widget.fuel_lbl.setText(str(self.fuel) + ' %')

        if self.reported_boo:
            self._widget.boo_led.setPalette(self.red_palette)
        else:
            self._widget.boo_led.setPalette(self.gray_palette)

        # Steering wheel buttons
        if self.on_off_btn:
            self._widget.on_off_led.setPalette(self.green_palette)
        else:
            self._widget.on_off_led.setPalette(self.gray_palette)

        if self.res_cncl_btn:
            self._widget.res_cncl_led.setPalette(self.green_palette)
        else:
            self._widget.res_cncl_led.setPalette(self.gray_palette)

        if self.set_inc_btn:
            self._widget.set_inc_led.setPalette(self.green_palette)
        else:
            self._widget.set_inc_led.setPalette(self.gray_palette)

        if self.set_dec_btn:
            self._widget.set_dec_led.setPalette(self.green_palette)
        else:
            self._widget.set_dec_led.setPalette(self.gray_palette)

        if self.gap_inc_btn:
            self._widget.gap_inc_led.setPalette(self.green_palette)
        else:
            self._widget.gap_inc_led.setPalette(self.gray_palette)

        if self.gap_dec_btn:
            self._widget.gap_dec_led.setPalette(self.green_palette)
        else:
            self._widget.gap_dec_led.setPalette(self.gray_palette)

        if self.la_on_off_btn:
            self._widget.la_on_off_led.setPalette(self.green_palette)
        else:
            self._widget.la_on_off_led.setPalette(self.gray_palette)

    def initGraphics(self):

        # LED color palettes
        self.green_palette = QPalette()
        self.green_palette.setColor(QPalette.Window, QColor(0, 255, 0))

        self.red_palette = QPalette()
        self.red_palette.setColor(QPalette.Window, QColor(255, 0, 0))

        self.yellow_palette = QPalette()
        self.yellow_palette.setColor(QPalette.Window, QColor(200, 200, 50))

        self.gray_palette = QPalette()
        self.gray_palette.setColor(QPalette.Window, QColor(80, 80, 80))

        # CAN RX LEDs
        self._widget.throttle_led.setText('')
        self._widget.throttle_led.setPalette(self.red_palette)
        self._widget.brake_led.setText('')
        self._widget.brake_led.setPalette(self.red_palette)
        self._widget.steering_led.setText('')
        self._widget.steering_led.setPalette(self.red_palette)
        self._widget.gear_led.setText('')
        self._widget.gear_led.setPalette(self.red_palette)

        # BOO LED
        self._widget.boo_led.setText('')
        self._widget.boo_led.setPalette(self.gray_palette)

        # Fault and driver override LEDs
        self._widget.throttle_driver_led.setText('')
        self._widget.throttle_driver_led.setPalette(self.gray_palette)
        self._widget.throttle_flt1_led.setText('')
        self._widget.throttle_flt1_led.setPalette(self.gray_palette)
        self._widget.throttle_flt2_led.setText('')
        self._widget.throttle_flt2_led.setPalette(self.gray_palette)
        self._widget.throttle_fltcon_led.setText('')
        self._widget.throttle_fltcon_led.setPalette(self.gray_palette)

        self._widget.brake_driver_led.setText('')
        self._widget.brake_driver_led.setPalette(self.gray_palette)
        self._widget.brake_flt1_led.setText('')
        self._widget.brake_flt1_led.setPalette(self.gray_palette)
        self._widget.brake_flt2_led.setText('')
        self._widget.brake_flt2_led.setPalette(self.gray_palette)
        self._widget.brake_fltcon_led.setText('')
        self._widget.brake_fltcon_led.setPalette(self.gray_palette)
        self._widget.brake_fltb_led.setText('')
        self._widget.brake_fltb_led.setPalette(self.gray_palette)

        self._widget.steering_driver_led.setText('')
        self._widget.steering_flt1_led.setText('')
        self._widget.steering_flt2_led.setText('')
        self._widget.steering_fltcon_led.setText('')

        self._widget.gear_driver_led.setText('')
        self._widget.gear_fltbus_led.setText('')

        # Steering wheel buttons
        self._widget.on_off_led.setText('')
        self._widget.on_off_led.setPalette(self.gray_palette)
        self._widget.res_cncl_led.setText('')
        self._widget.res_cncl_led.setPalette(self.gray_palette)
        self._widget.set_inc_led.setText('')
        self._widget.set_inc_led.setPalette(self.gray_palette)
        self._widget.set_dec_led.setText('')
        self._widget.set_dec_led.setPalette(self.gray_palette)
        self._widget.gap_inc_led.setText('')
        self._widget.gap_inc_led.setPalette(self.gray_palette)
        self._widget.gap_dec_led.setText('')
        self._widget.gap_dec_led.setPalette(self.gray_palette)
        self._widget.la_on_off_led.setText('')
        self._widget.la_on_off_led.setPalette(self.gray_palette)

    def bindCallbacks(self):
        pass

    def subscribeTopics(self):
        rospy.Subscriber('vehicle/throttle_report', ThrottleReport,
                         self.recvThrottleReport)
        rospy.Subscriber('vehicle/brake_report', BrakeReport,
                         self.recvBrakeReport)
        rospy.Subscriber('vehicle/steering_report', SteeringReport,
                         self.recvSteeringReport)
        rospy.Subscriber('vehicle/gear_report', GearReport,
                         self.recvGearReport)
        rospy.Subscriber('vehicle/misc1_report', Misc1Report,
                         self.recvMisc1Report)
        rospy.Subscriber('vehicle/tire_pressure_report', TirePressureReport,
                         self.recvTirePressure)
        rospy.Subscriber('vehicle/fuel_level_report', FuelLevelReport,
                         self.recvFuelLevel)
        rospy.Subscriber('vehicle/gps/fix', NavSatFix, self.recvGps)
        rospy.Subscriber('vehicle/imu/data_raw', Imu, self.recvImu)

    def recvImu(self, msg):
        self.yaw_rate = 1e-2 * math.floor(1e2 * msg.angular_velocity.z)
        self.roll_rate = 1e-2 * math.floor(1e2 * msg.angular_velocity.x)

    def recvGps(self, msg):
        self.gps_lat = 1e-6 * math.floor(1e6 * msg.latitude)
        self.gps_lon = 1e-6 * math.floor(1e6 * msg.longitude)

    def recvThrottleReport(self, msg):
        self.throttle_stamp = rospy.Time.now()
        self.reported_throttle = int(math.floor(100 * msg.pedal_output))
        self.throttle_cmd = int(math.floor(100 * msg.pedal_cmd))

        self.throttle_driver = msg.driver
        self.throttle_flt1 = msg.fault_ch1
        self.throttle_flt2 = msg.fault_ch2
        self.throttle_fltcon = msg.fault_connector

    def recvBrakeReport(self, msg):
        self.brake_stamp = rospy.Time.now()
        self.reported_brake = int(math.floor(100 * msg.pedal_output))
        self.brake_cmd = int(math.floor(100 * msg.pedal_cmd))
        self.reported_boo = msg.boo_output

        self.brake_driver = msg.driver
        self.brake_flt1 = msg.fault_ch1
        self.brake_flt2 = msg.fault_ch2
        self.brake_fltboo = msg.fault_boo
        self.brake_fltcon = msg.fault_connector

    def recvSteeringReport(self, msg):
        self.steering_stamp = rospy.Time.now()
        self.speed = 0.1 * math.floor(10 * msg.speed)
        self.reported_steering = 0.1 * math.floor(
            self.rad_to_deg * 10 * msg.steering_wheel_angle)
        self.steering_cmd = 0.1 * math.floor(
            self.rad_to_deg * 10 * msg.steering_wheel_angle_cmd)

        self.steering_driver = msg.driver
        self.steering_flt1 = msg.fault_bus1
        self.steering_flt2 = msg.fault_bus2
        self.steering_fltcon = msg.fault_connector

    def recvGearReport(self, msg):
        self.gear_stamp = rospy.Time.now()
        self.reported_gear = self.gear_map[msg.state.gear]

        self.gear_driver = msg.driver
        self.gear_fltbus = msg.fault_bus

    def recvMisc1Report(self, msg):
        self.on_off_btn = msg.btn_cc_on_off
        self.res_cncl_btn = msg.btn_cc_res_cncl
        self.set_inc_btn = msg.btn_cc_set_inc
        self.set_inc_btn = msg.btn_cc_set_dec
        self.set_inc_btn = msg.btn_cc_gap_inc
        self.set_inc_btn = msg.btn_cc_gap_dec
        self.set_inc_btn = msg.btn_la_on_off

    def advertiseTopics(self):
        pass

    def recvTirePressure(self, msg):
        self.fl_tire = msg.front_left
        self.fr_tire = msg.front_right
        self.rl_tire = msg.rear_left
        self.rr_tire = msg.rear_right

    def recvFuelLevel(self, msg):
        self.fuel = 0.1 * math.floor(10 * msg.fuel_level)

    def setupWidget(self, context):
        super(MkzGui, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName(self.gui_object_name)

        # Create QWidget
        self._widget = QWidget()

        # Get path to UI file which should be in the "resource" folder of this package
        ui_file = os.path.join(rospkg.RosPack().get_path(self.package_name),
                               'resource', self.ui_filename)
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self._widget)
        # Give QObjects reasonable names
        self._widget.setObjectName(self.gui_object_name)
        # Add widget to the user interface
        context.add_widget(self._widget)

        # Set up a timer to update the GUI
        update_timer = QTimer(self._widget)
        update_timer.setInterval(self.update_period)
        update_timer.setSingleShot(False)
        update_timer.timeout.connect(lambda: self.updateGuiCallback())
        update_timer.start()

    def shutdown_plugin(self):
        pass
Example #25
0
 def __init__(self, right=False, parent=None, show_open_in_editor=False):
     PlainTextEdit.__init__(self, parent)
     self.setFrameStyle(0)
     self.show_open_in_editor = show_open_in_editor
     self.side_margin = 0
     self.setContextMenuPolicy(Qt.CustomContextMenu)
     self.customContextMenuRequested.connect(self.show_context_menu)
     self.setFocusPolicy(Qt.NoFocus)
     self.right = right
     self.setReadOnly(True)
     w = self.fontMetrics()
     self.number_width = max(map(lambda x: w.width(str(x)), xrange(10)))
     self.space_width = w.width(' ')
     self.setLineWrapMode(self.WidgetWidth)
     self.setTabStopWidth(tprefs['editor_tab_stop_width'] *
                          self.space_width)
     font = self.font()
     ff = tprefs['editor_font_family']
     if ff is None:
         ff = default_font_family()
     font.setFamily(ff)
     font.setPointSize(tprefs['editor_font_size'])
     self.setFont(font)
     font = self.heading_font = QFont(self.font())
     font.setPointSize(int(tprefs['editor_font_size'] * 1.5))
     font.setBold(True)
     theme = get_theme(tprefs['editor_theme'])
     pal = self.palette()
     pal.setColor(pal.Base, theme_color(theme, 'Normal', 'bg'))
     pal.setColor(pal.AlternateBase, theme_color(theme, 'CursorLine', 'bg'))
     pal.setColor(pal.Text, theme_color(theme, 'Normal', 'fg'))
     pal.setColor(pal.Highlight, theme_color(theme, 'Visual', 'bg'))
     pal.setColor(pal.HighlightedText, theme_color(theme, 'Visual', 'fg'))
     self.setPalette(pal)
     self.viewport().setCursor(Qt.ArrowCursor)
     self.line_number_area = LineNumbers(self)
     self.blockCountChanged[int].connect(self.update_line_number_area_width)
     self.updateRequest.connect(self.update_line_number_area)
     self.line_number_palette = pal = QPalette()
     pal.setColor(pal.Base, theme_color(theme, 'LineNr', 'bg'))
     pal.setColor(pal.Text, theme_color(theme, 'LineNr', 'fg'))
     pal.setColor(pal.BrightText, theme_color(theme, 'LineNrC', 'fg'))
     self.line_number_map = LineNumberMap()
     self.search_header_pos = 0
     self.changes, self.headers, self.images = [], [], OrderedDict()
     self.setVerticalScrollBarPolicy(
         Qt.ScrollBarAlwaysOff), self.setHorizontalScrollBarPolicy(
             Qt.ScrollBarAlwaysOff)
     self.diff_backgrounds = {
         'replace':
         theme_color(theme, 'DiffReplace', 'bg'),
         'insert':
         theme_color(theme, 'DiffInsert', 'bg'),
         'delete':
         theme_color(theme, 'DiffDelete', 'bg'),
         'replacereplace':
         theme_color(theme, 'DiffReplaceReplace', 'bg'),
         'boundary':
         QBrush(theme_color(theme, 'Normal', 'fg'), Qt.Dense7Pattern),
     }
     self.diff_foregrounds = {
         'replace': theme_color(theme, 'DiffReplace', 'fg'),
         'insert': theme_color(theme, 'DiffInsert', 'fg'),
         'delete': theme_color(theme, 'DiffDelete', 'fg'),
         'boundary': QColor(0, 0, 0, 0),
     }
     for x in ('replacereplace', 'insert', 'delete'):
         f = QTextCharFormat()
         f.setBackground(self.diff_backgrounds[x])
         setattr(self, '%s_format' % x, f)
Example #26
0
    def initialize(self, parent, book_id, cid, installed_book,
                   enable_metadata_updates, marvin_db_path):
        '''
        __init__ is called on SizePersistedDialog()
        shared attributes of interest:
            .authors
            .author_sort
            .cover_hash
            .pubdate
            .publisher
            .series
            .series_index
            .title
            .title_sort
            .comments
            .tags
            .uuid
        '''
        self.setupUi(self)
        self.book_id = book_id
        self.cid = cid
        self.connected_device = parent.opts.gui.device_manager.device
        self.installed_book = installed_book
        self.marvin_db_path = marvin_db_path
        self.opts = parent.opts
        self.parent = parent
        self.stored_command = None
        self.verbose = parent.verbose
        self.BORDER_LR = 4
        self.BORDER_TB = 8
        self.GREY_FG = '<font style="color:#A0A0A0">{0}</font>'
        self.YELLOW_BG = '<font style="background:#FDFF99">{0}</font>'

        self._log_location(installed_book.title)

        # Subscribe to Marvin driver change events
        self.connected_device.marvin_device_signals.reader_app_status_changed.connect(
            self.marvin_status_changed)

        #self._log("mismatches:\n%s" % repr(installed_book.metadata_mismatches))
        self.mismatches = installed_book.metadata_mismatches

        self._populate_title()
        self._populate_title_sort()
        self._populate_series()
        self._populate_authors()
        self._populate_author_sort()
        self._populate_uuid()
        self._populate_covers()
        self._populate_subjects()
        self._populate_publisher()
        self._populate_pubdate()
        self._populate_description()

        # ~~~~~~~~ Export to Marvin button ~~~~~~~~
        self.export_to_marvin_button.setIcon(
            QIcon(
                os.path.join(self.parent.opts.resources_path, 'icons',
                             'from_calibre.png')))
        self.export_to_marvin_button.clicked.connect(
            partial(self.store_command, 'export_metadata'))
        self.export_to_marvin_button.setEnabled(enable_metadata_updates)

        # ~~~~~~~~ Import from Marvin button ~~~~~~~~
        self.import_from_marvin_button.setIcon(
            QIcon(
                os.path.join(self.parent.opts.resources_path, 'icons',
                             'from_marvin.png')))
        self.import_from_marvin_button.clicked.connect(
            partial(self.store_command, 'import_metadata'))
        self.import_from_marvin_button.setEnabled(enable_metadata_updates)

        # If no calibre book, or no mismatches, adjust the display accordingly
        if not self.cid:
            #self._log("self.cid: %s" % repr(self.cid))
            #self._log("self.mismatches: %s" % repr(self.mismatches))
            self.calibre_gb.setVisible(False)
            self.import_from_marvin_button.setVisible(False)
            self.setWindowTitle(u'Marvin metadata')
        elif not self.mismatches:
            # Show both panels, but hide the transfer buttons
            self.export_to_marvin_button.setVisible(False)
            self.import_from_marvin_button.setVisible(False)
        else:
            self.setWindowTitle(u'Metadata Summary')

        if False:
            # Set the Marvin QGroupBox to Marvin red
            marvin_red = QColor()
            marvin_red.setRgb(189, 17, 20, alpha=255)
            palette = QPalette()
            palette.setColor(QPalette.Background, marvin_red)
            self.marvin_gb.setPalette(palette)

        # ~~~~~~~~ Add a Close or Cancel button ~~~~~~~~
        self.close_button = QPushButton(QIcon(I('window-close.png')), 'Close')
        if self.mismatches:
            self.close_button.setText('Cancel')
        self.bb.addButton(self.close_button, QDialogButtonBox.RejectRole)

        self.bb.clicked.connect(self.dispatch_button_click)

        # Restore position
        self.resize_dialog()
 def setup_clear_button_palettes(self):
     # Color for clear_button_pallette
     self.orig_palette = self.clear_Btn.palette()
     self.pushme_palette = QPalette()
     self.pushme_palette.setColor(QPalette.ButtonText, Qt.red)
     self.set_clear_btn_color()
class BinaryDataForm2(QDialog, ui_binary_data_form.Ui_BinaryDataForm):
    def __init__(self, ma_unit, cur_txs, cur_group_str, cur_effect, parent=None):
        super(BinaryDataForm2, self).__init__(parent)
        self.setupUi(self)
        self._setup_signals_and_slots()
        self.ma_unit = ma_unit
        self.raw_data_d = {}
        for group in cur_txs:
            raw_data = self.ma_unit.get_raw_data_for_group(group)
            self.raw_data_d[group] = raw_data
        self.cur_groups = cur_txs
        print("CUR TXS: ",cur_txs)
        self.group_str = cur_group_str
        self.cur_effect = cur_effect
        self.entry_widgets = [self.raw_data_table, self.low_txt_box,
                              self.high_txt_box, self.effect_txt_box]
        self.already_showed_change_CI_alert = False
        
        meta_globals.init_ci_spinbox_and_label(self.CI_spinbox, self.ci_label)
        
        self.initialize_table_items() # initialize all cell to empty items
        self.setup_inconsistency_checking()
        self.initialize_backup_structures()
        
        # Color for clear_button_pallette
        self.setup_clear_button_palettes()
        
        self._update_raw_data()  # ma_unit --> table
        self._populate_effect_data()  # make combo boxes for effects
        self.set_current_effect()  # fill in current effect data in line edits
        self._update_data_table()  # fill in 2x2
        self.enable_back_calculation_btn()
        self.save_form_state()
        
    def initialize_table_items(self):
        ''' Initialize all cells to empty items '''
        print("Entering initialize_table_items")
        for row in range(3):
            for col in range(3):
                self._set_val(row, col, None)

    def setup_clear_button_palettes(self):
        # Color for clear_button_pallette
        self.orig_palette = self.clear_Btn.palette()
        self.pushme_palette = QPalette()
        self.pushme_palette.setColor(QPalette.ButtonText, Qt.red)
        self.set_clear_btn_color()
    
    def set_clear_btn_color(self):
        if self.input_fields_disabled():
            self.clear_Btn.setPalette(self.pushme_palette)
        else:
            self.clear_Btn.setPalette(self.orig_palette)
    
    def input_fields_disabled(self):
        table_disabled = True
        for row in range(3):
            for col in range(3):
                item = self.raw_data_table.item(row, col)
                if item is None:
                    continue
                if (item.flags() & Qt.ItemIsEditable) == Qt.ItemIsEditable:
                    table_disabled = False
                    
        txt_boxes_disabled = self._txt_boxes_disabled()

        if table_disabled and txt_boxes_disabled:
            self.CI_spinbox.setEnabled(False)  # weird place for ?this? but whatever
            return True
        return False

    def _txt_boxes_disabled(self):
        return not (self.effect_txt_box.isEnabled() or
                    self.low_txt_box.isEnabled() or
                    self.high_txt_box.isEnabled())
        
    def print_effects_dict_from_ma_unit(self):
        print self.ma_unit.get_effects_dict()
    
    def enable_back_calculation_btn(self, engage=False):
        print("Enabling back-calculation button...")

        def build_back_calc_args_dict():
            
            effect = self.cur_effect
            d = {}
            
            d["metric"] = str(effect)
            
            for key, R_key in zip(["est", "lower", "upper"], ["estimate", "lower", "upper"]):
                try:
                    d["%s" % R_key] = float(self.form_effects_dict[effect][key])
                except:
                    d["%s" % R_key] = None
            
            x = self.CI_spinbox.value()
            d["conf.level"] = x if _is_a_float(x) else None
            
            d["Ev_A"] = float(self._get_int(0, 0)) if not self._is_empty(0, 0) else None
            d["N_A"] = float(self._get_int(0, 2)) if not self._is_empty(0, 2) else None
            d["Ev_B"] = float(self._get_int(1, 0)) if not self._is_empty(1, 0) else None
            d["N_B"] = float(self._get_int(1, 2)) if not self._is_empty(1, 2) else None
            
            return d
        def new_data(bin_data, imputed):
            changed = False
            old_data = (bin_data["Ev_A"],
                        bin_data["N_A"],
                        bin_data["Ev_B"],
                        bin_data["N_B"])
            new_data = []
            new_data.append((int(round(imputed["op1"]["a"])),
                             int(round(imputed["op1"]["b"])),
                             int(round(imputed["op1"]["c"])),
                             int(round(imputed["op1"]["d"])),
                             ))
            if "op2" in imputed:
                new_data.append((int(round(imputed["op2"]["a"])),
                                 int(round(imputed["op2"]["b"])),
                                 int(round(imputed["op2"]["c"])),
                                 int(round(imputed["op2"]["d"])),
                                 ))
            def new_item_available(old,new):
                isBlank = lambda x: x in meta_globals.EMPTY_VALS
                no_longer_blank = isBlank(old) and not isBlank(new)
                return no_longer_blank
                #if (old is not None) and (new is not None):
                #    return old != new
            comparison0 = [new_item_available(old_data[i], new_data[0][i]) for i in range(len(old_data))]
            new_data_in_op1 = any(comparison0)
            print("Comparison0:", comparison0)

            if new_data_in_op1:
                changed = True
                if "op2" in imputed:
                    comparison1 = [new_item_available(old_data[i], new_data[1][i]) for i in range(len(old_data))]
                    print("Comparison1:", comparison1)
                    new_data_in_op2 = any(comparison1)
                    if not new_data_in_op2:
                        changed = False
            else:
                changed = False
                
            return changed
        ### end of new_data() definition ####
            
        # Makes no sense to show the button on a form where the back calculation is not implemented
        if not self.cur_effect in ["OR", "RR", "RD"]:
            self.back_calc_btn.setVisible(False)
            return None
        else:
            self.back_calc_btn.setVisible(True)
            
        bin_data = build_back_calc_args_dict()
        print("Binary data for back-calculation:", bin_data)
        
        imputed = meta_py_r.impute_bin_data(bin_data.copy())
        print("Imputed data: %s", imputed)
        
        # Leave if nothing was imputed
        if "FAIL" in imputed:
            print("Fail to impute")
            self.back_calc_btn.setEnabled(False)
            return None
        
        if new_data(bin_data, imputed):
            self.back_calc_btn.setEnabled(True)
        else:
            self.back_calc_btn.setEnabled(False)
        
        self.set_clear_btn_color()
        
        if not engage:
            return None
        ########################################################################
        # Actually do stuff with imputed data here if we are 'engaged'
        ########################################################################
        for x in range(3):
            self.clear_column(x)  # clear out the table

        if len(imputed.keys()) > 1:
            dialog = ChooseBackCalcResultForm(imputed, parent=self)
            if dialog.exec_():
                choice = dialog.getChoice()
            else:  # don't do anything if cancelled
                return None
        else:  # only one option
            choice = "op1"
            
            
        # set values in table & save in ma_unit
        self.raw_data_table.blockSignals(True)
        self._set_val(0, 0, int(round(imputed[choice]["a"])))
        self._set_val(0, 2, int(round(imputed[choice]["b"])))  
        self._set_val(1, 0, int(round(imputed[choice]["c"]))) 
        self._set_val(1, 2, int(round(imputed[choice]["d"]))) 
        self.raw_data_table.blockSignals(False)
        
        self._update_data_table()
        self._update_ma_unit()  # save in ma_unit
        self.save_form_state()
        
        self.set_clear_btn_color()

    def setup_inconsistency_checking(self):
        # set-up inconsistency label
        inconsistency_palette = QPalette()
        inconsistency_palette.setColor(QPalette.WindowText, Qt.red)
        self.inconsistencyLabel.setPalette(inconsistency_palette)
        self.inconsistencyLabel.setVisible(False)
        
        def action_consistent_table():    
            self.inconsistencyLabel.setVisible(False)
            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
        def action_inconsistent_table():
            # show label, disable OK buttonbox button
            self.inconsistencyLabel.setVisible(True)
            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
        
        self.check_table_consistency = meta_globals.ConsistencyChecker(
                            fn_consistent=action_consistent_table,
                            fn_inconsistent=action_inconsistent_table,
                            table_2x2=self.raw_data_table)

    def initialize_backup_structures(self):
        # Stores form effect info as text
        self.form_effects_dict = {}
        # self.form_effects_dict["alpha"] = ""
        for effect in self.get_effect_names():
            self.form_effects_dict[effect] = {"est":"", "lower":"", "upper":""}
        
        # Stores table items as text
        self.table_backup = [[None, None, None], [None, None, None], [None, None, None]]
    
    @pyqtSignature("int, int, int, int")
    def on_raw_data_table_currentCellChanged(self, currentRow, currentColumn, previousRow, previousColumn):
        self.current_item_data = self._get_int(currentRow, currentColumn)
        print "Current Item Data:", self.current_item_data
        
    def _setup_signals_and_slots(self):
        QObject.connect(self.raw_data_table, SIGNAL("cellChanged (int, int)"), self.cell_changed)
        QObject.connect(self.effect_cbo_box, SIGNAL("currentIndexChanged(QString)"), self.effect_changed)
        QObject.connect(self.clear_Btn, SIGNAL("clicked()"), self.clear_form)
        
        QObject.connect(self.effect_txt_box, SIGNAL("textEdited(QString)"), lambda new_text : self.val_edit("est", new_text))
        QObject.connect(self.low_txt_box, SIGNAL("textEdited(QString)"), lambda new_text : self.val_edit("lower", new_text))
        QObject.connect(self.high_txt_box, SIGNAL("textEdited(QString)"), lambda new_text : self.val_edit("upper", new_text))
        
        QObject.connect(self.effect_txt_box, SIGNAL("editingFinished()"), lambda: self.val_changed("est"))
        QObject.connect(self.low_txt_box, SIGNAL("editingFinished()"), lambda: self.val_changed("lower"))
        QObject.connect(self.high_txt_box, SIGNAL("editingFinished()"), lambda: self.val_changed("upper"))
        
        QObject.connect(self.back_calc_btn, SIGNAL("clicked()"), lambda: self.enable_back_calculation_btn(engage=True))
        QObject.connect(self.CI_spinbox, SIGNAL("valueChanged(double)"), self._change_ci)
        
        QObject.connect(self, SIGNAL("accepted()"), self.reset_conf_level)
    
    def _change_ci(self, val):
        self.ci_label.setText("{0:.1F} % Confidence Interval".format(val))
        print("New CI val:", val)
        
        self.change_CI_alert(val)
        self.enable_back_calculation_btn()
                                                                                              
    def _populate_effect_data(self):
        q_effects = sorted([QString(effect_str) for effect_str in self.ma_unit.effects_dict.keys()])
        self.effect_cbo_box.blockSignals(True)
        self.effect_cbo_box.addItems(q_effects)
        self.effect_cbo_box.blockSignals(False)
        self.effect_cbo_box.setCurrentIndex(q_effects.index(QString(self.cur_effect)))
        
    def get_effect_names(self):
        return self.ma_unit.get_effect_names()
    
    def set_current_effect(self):
        '''Fills in text boxes with data from ma unit'''
        
        print("Entering set_current_effect")
        
        # Fill in text boxes with data from ma unit
        self.block_all_signals(True)
        effect_dict = self.ma_unit.get_effect_dict(self.cur_effect, self.group_str)
        for s, txt_box in zip(['display_est', 'display_lower', 'display_upper'], \
                              [self.effect_txt_box, self.low_txt_box, self.high_txt_box]):
            if effect_dict[s] is not None:
                txt_box.setText(QString("%s" % round(effect_dict[s], NUM_DIGITS)))
            else:
                txt_box.setText(QString(""))
        self.block_all_signals(False)
        
        self.change_row_color_according_to_metric()
        
    def change_row_color_according_to_metric(self):
        # Change color of bottom rows of table according one or two-arm metric
        curr_effect_is_one_arm = self.cur_effect in BINARY_ONE_ARM_METRICS
        #ungreyed_brush = self.raw_data_table.item(0,0).background()
        for row in (1,2):
            for col in range(3):
                item = self.raw_data_table.item(row, col)
                if curr_effect_is_one_arm:
                    item.setBackground(QBrush(QColor(Qt.gray)))
                else:
                    # just reset the item
                    text = item.text()
                    self.raw_data_table.blockSignals(True)
                    popped_item = self.raw_data_table.takeItem(row, col)
                    self.raw_data_table.blockSignals(False)
                    del popped_item
                    self._set_val(row, col, text)
 
    def effect_changed(self):
        '''Called when a new effect is selected in the combo box'''
        
        # Re-scale previous effect first
        self.reset_conf_level()
        
        self.cur_effect = unicode(self.effect_cbo_box.currentText().toUtf8(), "utf-8")
        self.group_str = self.get_cur_group_str()
        
        self.try_to_update_cur_outcome()
        self.set_current_effect()
        
        self.enable_txt_box_input()
        self.enable_back_calculation_btn()
        
    def save_form_state(self):
        ''' Saves the state of all objects on the form '''
        
        print("Saving form state...")
        
        def save_table_data():
            for row in range(3):
                for col in range(3):
                    item = self.raw_data_table.item(row, col)
                    contents = "" if item is None else item.text()
                    self.table_backup[row][col] = contents
                    
        def save_displayed_effects_data(effect=None):
            print "Saving Displayed Effects data...."
            
            if effect is None:
                effect = self.cur_effect
            
            self.form_effects_dict[effect]["est"] = self.effect_txt_box.text() 
            self.form_effects_dict[effect]["lower"] = self.low_txt_box.text()    
            self.form_effects_dict[effect]["upper"] = self.high_txt_box.text()    
        
            self.candidate_est = self.effect_txt_box.text()
            self.candidate_lower = self.low_txt_box.text()
            self.candidate_upper = self.high_txt_box.text()

        save_table_data()
        save_displayed_effects_data()
        self.enable_back_calculation_btn()
    
    def block_all_signals(self, state):
        for widget in self.entry_widgets:
            widget.blockSignals(state)
        
    def restore_form_state(self):
        ''' Restores the state of all objects on the form '''
        
        # Block all signals on the form 
        self.block_all_signals(True)
        ########################################################################
        
        def restore_displayed_effects_data():
            print "Restoring displayed effects data..."
            
            self.effect_txt_box.setText(self.form_effects_dict[self.cur_effect]["est"])    
            self.low_txt_box.setText(self.form_effects_dict[self.cur_effect]["lower"])       
            self.high_txt_box.setText(self.form_effects_dict[self.cur_effect]["upper"])                     
            
            self.candidate_est = self.effect_txt_box.text()
            self.candidate_lower = self.low_txt_box.text()
            self.candidate_upper = self.high_txt_box.text()
        
        def restore_table():
            # print "Table to restore:"
            # self.print_backup_table()
        
            for row in range(3):
                for col in range(3):
                    self.raw_data_table.blockSignals(True)
                    self._set_val(row, col, self.table_backup[row][col])
                    self.raw_data_table.blockSignals(False)
            self.check_table_consistency.run()
            
            # print("Backed-up table:")
            # self.print_backup_table()
        
        self.CI_spinbox.setValue(meta_py_r.get_global_conf_level())
        restore_displayed_effects_data()
        restore_table()
        self.enable_back_calculation_btn()
        ########################################################################
        # Unblock the signals
        self.block_all_signals(False)
        
    def val_changed(self, val_str):        
        print "--------------\nEntering val_changed...."
        
        def is_between_bounds(est=self.form_effects_dict[self.cur_effect]["est"],
                              low=self.form_effects_dict[self.cur_effect]["lower"],
                              high=self.form_effects_dict[self.cur_effect]["upper"]):
            return meta_globals.between_bounds(est=est, low=low, high=high)

        ###### ERROR CHECKING CODE#####
        # Make sure entered value is numeric and between the appropriate bounds
        self.block_all_signals(True)
        float_msg = "Must be numeric!"

        try:
            if val_str == "est" and not _is_empty(self.candidate_est):
                # Check type
                if not _is_a_float(self.candidate_est) :
                    QMessageBox.warning(self, "whoops", float_msg)
                    raise Exception("error")
                (good_result, msg) = is_between_bounds(est=self.candidate_est)
                if not good_result:
                    QMessageBox.warning(self, "whoops", msg)
                    raise Exception("error")
                display_scale_val = float(self.candidate_est)
            elif val_str == "lower" and not _is_empty(self.candidate_lower):
                if not _is_a_float(self.candidate_lower) :
                    QMessageBox.warning(self, "whoops", float_msg)
                    raise Exception("error")
                (good_result, msg) = is_between_bounds(low=self.candidate_lower)
                if not good_result:
                    QMessageBox.warning(self, "whoops", msg)
                    raise Exception("error")
                display_scale_val = float(self.candidate_lower)
            elif val_str == "upper" and not _is_empty(self.candidate_upper): 
                if not _is_a_float(self.candidate_upper) :
                    QMessageBox.warning(self, "whoops", float_msg)
                    raise Exception("error")
                (good_result, msg) = is_between_bounds(high=self.candidate_upper)
                if not good_result:
                    QMessageBox.warning(self, "whoops", msg)
                    raise Exception("error")
                display_scale_val = float(self.candidate_upper)
        except:
            print "Error flag is true"
            self.restore_form_state()
            self.block_all_signals(True)
            if val_str == "est":
                self.effect_txt_box.setFocus()
            elif val_str == "lower":
                self.low_txt_box.setFocus()
            elif val_str == "upper":
                self.high_txt_box.setFocus()
            self.block_all_signals(False)
            return
        
        self.block_all_signals(False)
        # If we got to this point it means everything is ok so far
        
        try:
            display_scale_val = float(display_scale_val)
        except:
            # a number wasn't entered; ignore
            # should probably clear out the box here, too.
            print "fail."
            return None
            
        calc_scale_val = meta_py_r.binary_convert_scale(display_scale_val, \
                                        self.cur_effect, convert_to="calc.scale")
                      
        if val_str == "est":
            self.ma_unit.set_effect(self.cur_effect, self.group_str, calc_scale_val)
            self.ma_unit.set_display_effect(self.cur_effect, self.group_str, display_scale_val)
        elif val_str == "lower":
            self.ma_unit.set_lower(self.cur_effect, self.group_str, calc_scale_val)
            self.ma_unit.set_display_lower(self.cur_effect, self.group_str, display_scale_val)
        else:
            self.ma_unit.set_upper(self.cur_effect, self.group_str, calc_scale_val)
            self.ma_unit.set_display_upper(self.cur_effect, self.group_str, display_scale_val)
        
        self.enable_txt_box_input()
        self.save_form_state()
        self.enable_back_calculation_btn()
    
    def val_edit(self, val_str, display_scale_val):
        # print "Editing %s with value: %s" % (val_str,display_scale_val)
        if val_str == "est":
            self.candidate_est = display_scale_val
        if val_str == "lower":
            self.candidate_lower = display_scale_val
        if val_str == "upper":
            self.candidate_upper = display_scale_val
        
    def _update_raw_data(self):
        ''' Generates the 2x2 table with whatever parametric data was provided '''
        ''' Sets #events and #subjects in binary table'''

        for row, group in enumerate(self.cur_groups):
            for col in (0, 2):
                adjusted_index = 0 if col == 0 else 1
                val = self.raw_data_d[group][adjusted_index]
                self._set_val(row, col, val)
      
    def _update_ma_unit(self):
        ''' Copy data from binary data table to the MA_unit'''
        ''' 
        Walk over the entries in the matrix (which may have been updated
        via imputation in the cell_changed method) corresponding to the 
        raw data in the underlying meta-analytic unit and update the values.
        '''
        for row in range(2):
            for col in (0, 2):
                adjusted_col = 1 if col == 2 else 0
                self.raw_data_d[self.cur_groups[row]][adjusted_col] = self._get_int(row, col)  # TODO: ENC
                print "%s, %s: %s" % (row, col, self._get_int(row, col))
        print "ok -- raw data is now: %s" % self.raw_data_d
        
    def _cell_data_not_valid(self, celldata_string):
        # ignore blank entries
        if celldata_string.trimmed() == "" or celldata_string is None:
            return None

        if not meta_globals._is_a_float(celldata_string):
            return "Raw data needs to be numeric."

        if not meta_globals._is_an_int(celldata_string):
            return "Expecting count data -- you provided a float (?)"

        if int(celldata_string) < 0:
            return "Counts cannot be negative."
        return None
        
    def cell_changed(self, row, col):
        # tries to make sense of user input before passing
        # on to the R routine
        
        print("Entering cell changed...")
        print("New cell data(%d,%d): %s" % (row, col, self.raw_data_table.item(row, col).text()))
        
        try:
            # Test if entered data is valid (a number)
            warning_msg = self._cell_data_not_valid(self.raw_data_table.item(row, col).text())
            if warning_msg:
                raise Exception("Invalid Cell Data")
    
            self._update_data_table()  # calculate rest of table (provisionally) based on new entry
            warning_msg = self.check_table_consistency.run()
            if warning_msg:
                raise Exception("Table no longer consistent.")
        except Exception as e:
            msg = e.args[0]
            QMessageBox.warning(self.parent(), "whoops", msg)  # popup warning
            self.restore_form_state()  # brings things back to the way they were
            return  # and leave
        
        self.save_form_state()    
        self._update_ma_unit()  # table widget --> ma_unit
        self.try_to_update_cur_outcome()  # update metric
        self.enable_back_calculation_btn()
        self.save_form_state()
        
        # disable just-edited cell
        self.block_all_signals(True)
        item = self.raw_data_table.item(row, col)
        newflags = item.flags() & ~Qt.ItemIsEditable
        item.setFlags(newflags)
        self.block_all_signals(False)
        
        self.enable_txt_box_input()  # if the effect was imputed
        self.set_clear_btn_color()
        
    def _get_table_vals(self):
        ''' Package table from 2x2 table in to a dictionary'''
        
        vals_d = {}
        vals_d["c11"] = self._get_int(0, 0)
        vals_d["c12"] = self._get_int(0, 1)
        vals_d["c21"] = self._get_int(1, 0)
        vals_d["c22"] = self._get_int(1, 1)
        vals_d["r1sum"] = self._get_int(0, 2)
        vals_d["r2sum"] = self._get_int(1, 2)
        vals_d["c1sum"] = self._get_int(2, 0)
        vals_d["c2sum"] = self._get_int(2, 1)
        vals_d["total"] = self._get_int(2, 2)
        return vals_d
    
    def clear_column(self, col):
        '''Clears out column in table and ma_unit'''

        for row in range(3):
            self.raw_data_table.blockSignals(True)
            self._set_val(row, col, None)  
            self.raw_data_table.blockSignals(False)
        
        self._update_ma_unit()
        self.save_form_state()
         
    def _set_vals(self, computed_d):
        '''Sets values in table widget'''
        self.raw_data_table.blockSignals(True)
        self._set_val(0, 0, computed_d["c11"])
        self._set_val(0, 1, computed_d["c12"])
        self._set_val(1, 0, computed_d["c21"])
        self._set_val(1, 1, computed_d["c22"])  
        self._set_val(0, 2, computed_d["r1sum"])
        self._set_val(1, 2, computed_d["r2sum"])
        self._set_val(2, 0, computed_d["c1sum"])
        self._set_val(2, 1, computed_d["c2sum"])  
        self._set_val(2, 2, computed_d["total"])  
        self.raw_data_table.blockSignals(False)  
        
    def _set_val(self, row, col, val):
        if meta_globals.is_NaN(val):  # get out quick
            print "%s is not a number" % val
            return
        
        try:
            self.raw_data_table.blockSignals(True)
            str_val = "" if val in EMPTY_VALS else str(int(val))
            if self.raw_data_table.item(row, col) == None:
                self.raw_data_table.setItem(row, col, QTableWidgetItem(str_val))
            else:
                self.raw_data_table.item(row, col).setText(str_val)
            print("    setting (%d,%d) to '%s'" % (row,col,str_val))
            
            # disable item
            if str_val != "": 
                item = self.raw_data_table.item(row, col)
                newflags = item.flags() & ~Qt.ItemIsEditable
                item.setFlags(newflags)
                
            self.raw_data_table.blockSignals(False)
        except:
            print("    Got to except in _set_val when trying to set (%d,%d)" % (row, col))
            raise
 
    def _build_dict(self):
        d = dict(zip(["control.n.outcome", "control.N", "tx.n.outcome", "tx.N"], self.raw_data))
        d["estimate"] = self.ma_unit.get_estimate(self.cur_effect, self.group_str)
        return d
        
    def _update_data_table(self):        
        '''Fill in 2x2 table from other entries in the table '''
        
        self.raw_data_table.blockSignals(True)
        
        params = self._get_table_vals()
        computed_params = meta_globals.compute_2x2_table(params)
        print "Computed Params", computed_params
        if computed_params:
            self._set_vals(computed_params)  # computed --> table widget
            
        self.raw_data_table.blockSignals(False)
        
    def _is_empty(self, i, j):
        val = self.raw_data_table.item(i, j)
        return val is None or val.text() == ""
        
    def _get_int(self, i, j):
        '''Get value from cell specified by row=i, col=j as an integer'''
        if not self._is_empty(i, j):
            val = int(float(self.raw_data_table.item(i, j).text()))
            print("Val from _get_int: %d" % val)
            return val
        else:
            return None  # its good to be explicit
            
    def _isBlank(self, x):
        return x is None or x == ""
        
    def try_to_update_cur_outcome(self):
        print("Entering try_to_update_cur_outcome...")
        print("    current effect: %s" % self.cur_effect)
        
        e1, n1, e2, n2 = self.ma_unit.get_raw_data_for_groups(self.cur_groups)
        print("    e1: %s, n1: %s, e2: %s, n2: %s" % (str(e1),str(n1),str(e2),str(n2)))
        
        two_arm_raw_data_ok = not any([self._isBlank(x) for x in [e1, n1, e2, n2]])
        one_arm_raw_data_ok = not any([self._isBlank(x) for x in [e1, n1]])
        curr_effect_is_one_arm = self.cur_effect in BINARY_ONE_ARM_METRICS
        curr_effect_is_two_arm = self.cur_effect in BINARY_TWO_ARM_METRICS
        
        # if None is in the raw data, should we clear out current outcome?
        if two_arm_raw_data_ok or (curr_effect_is_one_arm and one_arm_raw_data_ok):
            if curr_effect_is_two_arm:
                est_and_ci_d = meta_py_r.effect_for_study(e1, n1, e2, n2, metric=self.cur_effect, conf_level=self.CI_spinbox.value())
            else:
                # binary, one-arm
                est_and_ci_d = meta_py_r.effect_for_study(e1, n1, two_arm=False, metric=self.cur_effect, conf_level=self.CI_spinbox.value())
        
            display_est, display_low, display_high = est_and_ci_d["display_scale"]
            self.ma_unit.set_display_effect_and_ci(self.cur_effect, self.group_str, display_est, display_low, display_high)                            
            est, low, high = est_and_ci_d["calc_scale"]  # calculation (e.g., log) scale
            self.ma_unit.set_effect_and_ci(self.cur_effect, self.group_str, est, low, high)
            self.set_current_effect()
           
    def clear_form(self):
        keys = ["c11", "c12", "r1sum", "c21", "c22", "r2sum", "c1sum", "c2sum", "total"]
        blank_vals = dict(zip(keys, [""] * len(keys)))

        self._set_vals(blank_vals)
        self._update_ma_unit()
        
        # clear out effects stuff
        for metric in BINARY_ONE_ARM_METRICS + BINARY_TWO_ARM_METRICS:
            if ((self.cur_effect in BINARY_TWO_ARM_METRICS and metric in BINARY_TWO_ARM_METRICS) or
                (self.cur_effect in BINARY_ONE_ARM_METRICS and metric in BINARY_ONE_ARM_METRICS)):
                self.ma_unit.set_effect_and_ci(metric, self.group_str, None, None, None)
                self.ma_unit.set_display_effect_and_ci(metric, self.group_str, None, None, None)
            else:
                # TODO: Do nothing for now..... treat the case where we have to switch group strings down the line
                pass
            
        # clear line edits
        self.set_current_effect()
        self.save_form_state()
        
        self.reset_table_item_flags()
        self.initialize_backup_structures()
        self.enable_txt_box_input()
        self.CI_spinbox.setValue(meta_py_r.get_global_conf_level())
        self.CI_spinbox.setEnabled(True)
        
    def enable_txt_box_input(self):
        # meta_globals.enable_txt_box_input(self.effect_txt_box, self.low_txt_box,
        #                                  self.high_txt_box)
        # print("Enabled text box input")
        pass
        
    def reset_table_item_flags(self):
        self.block_all_signals(True)
        for row in range(3):
            for col in range(3):
                item = self.raw_data_table.item(row, col)
                if not item is None:
                    newflags = item.flags() | Qt.ItemIsEditable
                    item.setFlags(newflags)
        self.block_all_signals(False)
        
    def change_CI_alert(self, value=None):
        if not self.already_showed_change_CI_alert:
            QMessageBox.information(self, "Changing Confidence Level", meta_globals.get_CHANGE_CI_ALERT_MSG())
            self.already_showed_change_CI_alert = True
    
    # TODO: should be refactored to shared function in meta_globals
    def reset_conf_level(self):
        print("Re-scaling est, low, high to standard confidence level")
        
        old_effect_and_ci = self.ma_unit.get_effect_and_ci(self.cur_effect, self.group_str)
        
        argument_d = {"est"  : old_effect_and_ci[0],
                      "low"  : old_effect_and_ci[1],
                      "high" : old_effect_and_ci[2],
                      "orig.conf.level": self.CI_spinbox.value(),
                      "target.conf.level": meta_py_r.get_global_conf_level()}
        
        res = meta_py_r.rescale_effect_and_ci_conf_level(argument_d)
        if "FAIL" in res:
            print("Could not reset confidence level")
            return
        
        res["display_est"] = meta_py_r.binary_convert_scale(res["est"], self.cur_effect, convert_to="display.scale")
        res["display_low"] = meta_py_r.binary_convert_scale(res["low"], self.cur_effect, convert_to="display.scale")
        res["display_high"] = meta_py_r.binary_convert_scale(res["high"], self.cur_effect, convert_to="display.scale")
        
        # Save results in ma_unit
        self.ma_unit.set_effect_and_ci(self.cur_effect, self.group_str, res["est"], res["low"], res["high"])
        self.ma_unit.set_display_effect_and_ci(self.cur_effect, self.group_str, res["display_est"], res["display_low"], res["display_high"])
        
    def get_cur_group_str(self):
        # Inspired from get_cur_group_str of ma_data_table_model
        
        if self.cur_effect in BINARY_ONE_ARM_METRICS:
            group_str = self.cur_groups[0] 
        else:
            group_str = "-".join(self.cur_groups)
        return group_str
class DiagnosticDataForm(QDialog, Ui_DiagnosticDataForm):
    def __init__(self, ma_unit, cur_txs, cur_group_str, parent=None):
        super(DiagnosticDataForm, self).__init__(parent)
        self.setupUi(self)
        self.setup_signals_and_slots()
        self.ma_unit = ma_unit
        self.raw_data_dict = {}
        for group in cur_txs:
            raw_data = self.ma_unit.get_raw_data_for_group(group)
            self.raw_data_dict[group] = raw_data
        self.cur_groups = cur_txs
        self.group_str = cur_group_str
        self.cur_effect = "Sens" # arbitrary
        
        self.entry_widgets = [self.two_by_two_table, self.prevalence_txt_box,
                              self.low_txt_box, self.high_txt_box,
                              self.effect_txt_box,]
        self.already_showed_change_CI_alert = False
        
        # block all the widgets for a moment
        self.block_all_signals(True)
        
        meta_globals.init_ci_spinbox_and_label(self.CI_spinbox, self.ci_label)
        
        self.setup_inconsistency_checking()
        self.initialize_backup_structures()
        self.setup_clear_button_palettes()
        
        self.setup_table_effect_dict()         # gather effect info from ma_unit
        self._read_in_table_data_from_MAunit() # populate table items from raw data in ma_unit
        self._populate_effect_cmbo_box()     # make cmbo box entries for effects
        self._update_data_table()         # fill in the rest of the data table
        self.set_current_effect()         # fill in current effect data in line edits
        self.enable_back_calculation_btn()
        self.enable_txt_box_input()
        self.save_form_state()

        # unblock
        self.block_all_signals(False)
        
        # Color for clear_button_pallette
        self.orig_palette = self.clear_Btn.palette()
        self.pushme_palette = QPalette()
        self.pushme_palette.setColor(QPalette.ButtonText,Qt.red)
        self.set_clear_btn_color()
        
    def setup_clear_button_palettes(self):
        # Color for clear_button_pallette
        self.orig_palette = self.clear_Btn.palette()
        self.pushme_palette = QPalette()
        self.pushme_palette.setColor(QPalette.ButtonText,Qt.red)
        self.set_clear_btn_color()
        
    def initialize_backup_structures(self):
        # Stores form effect info as text
        self.form_effects_dict = {"Sens":{"est":"","lower":"","upper":""},
                                  "Spec":{"est":"","lower":"","upper":""},
                                  "prevalence":""}
        # Stores table items as text
        self.table_backup = [[None,None,None],[None,None,None],[None,None,None]]
    
    def setup_signals_and_slots(self):
        QObject.connect(self.two_by_two_table, SIGNAL("cellChanged (int, int)"), self.cell_changed)                          
        QObject.connect(self.effect_cbo_box, SIGNAL("currentIndexChanged(QString)"), self.effect_changed) 
        QObject.connect(self.clear_Btn, SIGNAL("clicked()"), self.clear_form)
        
        QObject.connect(self.effect_txt_box, SIGNAL("textEdited(QString)"), lambda new_text : self.val_edit("est", new_text))
        QObject.connect(self.low_txt_box,    SIGNAL("textEdited(QString)"), lambda new_text : self.val_edit("lower", new_text))
        QObject.connect(self.high_txt_box,   SIGNAL("textEdited(QString)"), lambda new_text : self.val_edit("upper", new_text))
        QObject.connect(self.prevalence_txt_box, SIGNAL("textEdited(QString)"), lambda new_text : self.val_edit("prevalence", new_text))
        
        QObject.connect(self.effect_txt_box, SIGNAL("editingFinished()"), lambda: self.val_changed("est")   )
        QObject.connect(self.low_txt_box,    SIGNAL("editingFinished()"), lambda: self.val_changed("lower") )
        QObject.connect(self.high_txt_box,   SIGNAL("editingFinished()"), lambda: self.val_changed("upper") )
        QObject.connect(self.prevalence_txt_box, SIGNAL("editingFinished()"), lambda: self.val_changed("prevalence") )

        QObject.connect(self.back_calc_Btn, SIGNAL("clicked()"), lambda: self.enable_back_calculation_btn(engage=True) )
        QObject.connect(self.CI_spinbox, SIGNAL("valueChanged(double)"), self._change_ci)
        QObject.connect(self, SIGNAL("accepted()"), self.reset_conf_level)
        
    def _change_ci(self,val):
        self.ci_label.setText("{0:.1F} % Confidence Interval".format(val))
        print("New CI val:",val)
        
        self.change_CI_alert(val)
        self.enable_back_calculation_btn()

    def setup_inconsistency_checking(self):
        # set-up inconsistency label
        inconsistency_palette = QPalette()
        inconsistency_palette.setColor(QPalette.WindowText,Qt.red)
        self.inconsistencyLabel.setPalette(inconsistency_palette)
        self.inconsistencyLabel.setVisible(False)
        
        def action_consistent_table():    
            self.inconsistencyLabel.setVisible(False)
            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
        def action_inconsistent_table():
            #show label, disable OK buttonbox button
            self.inconsistencyLabel.setVisible(True)
            self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
        
        self.check_table_consistency = meta_globals.ConsistencyChecker(
                            fn_consistent=action_consistent_table,
                            fn_inconsistent=action_inconsistent_table,
                            table_2x2 = self.two_by_two_table)

    def _get_int(self, i, j):
        try:
            if not self._is_empty(i,j):
                int_val = int(float(self.two_by_two_table.item(i, j).text()))
                return int_val
        except:
            # Should never appear....
            msg = "Could not convert %s to integer" % self.two_by_two_table.item(i, j)
            QMessageBox.warning(self.parent(), "whoops", msg)
            raise Exception("Could not convert %s to int" % self.two_by_two_table.item(i, j))
            
    def cell_data_invalid(self, celldata_string):
        # ignore blank entries
        if celldata_string.trimmed() == "" or celldata_string is None:
            return None

        if not meta_globals._is_a_float(celldata_string):
            return "Raw data needs to be numeric."

        if not meta_globals._is_an_int(celldata_string):
            return "Expecting count data -- you provided a float (?)"

        if int(celldata_string) < 0:
            return "Counts cannot be negative."
        return None

    def _is_empty(self, i, j):
        val = self.two_by_two_table.item(i,j)
        return val is None or val.text() == "" or val.text() == None
    def _is_invalid(self, i, j):
        val = self.two_by_two_table.item(i,j)
        try:
            int(val.text())
        except:
            return True
        return False
    
    def _is_txt_box_invalid(self, txt_box):
        val = txt_box.text()
        empty = val in EMPTY_VALS
        return meta_globals.is_NaN(val) or empty or (not _is_a_float(val))
    
    def _set_val(self, row, col, val):
        if meta_globals.is_NaN(val): # get out quick
            print "%s is not a number" % val
            return
        
        try:
            str_val = "" if val in EMPTY_VALS else str(int(val))
            self.two_by_two_table.blockSignals(True)
            if self.two_by_two_table.item(row, col) == None:
                self.two_by_two_table.setItem(row, col, QTableWidgetItem(str_val))
            else:
                self.two_by_two_table.item(row, col).setText(str_val)
            self.two_by_two_table.blockSignals(False)
            
            if str_val != "": #disable item
                self.two_by_two_table.blockSignals(True)
                item = self.two_by_two_table.item(row, col)
                newflags = item.flags() & ~Qt.ItemIsEditable
                item.setFlags(newflags)
                self.two_by_two_table.blockSignals(False)
        except:
            print("Got to except in _set_val when trying to set (%d,%d)" % (row,col)) 
    
    def _set_vals(self, computed_d):
        '''Sets values in table widget'''
        
        self.two_by_two_table.blockSignals(True)
        self._set_val(0, 0, computed_d["c11"])
        self._set_val(0, 1, computed_d["c12"])
        self._set_val(1, 0, computed_d["c21"])
        self._set_val(1, 1, computed_d["c22"])  
        self._set_val(0, 2, computed_d["r1sum"])
        self._set_val(1, 2, computed_d["r2sum"])
        self._set_val(2, 0, computed_d["c1sum"])
        self._set_val(2, 1, computed_d["c2sum"])  
        self._set_val(2, 2, computed_d["total"])  
        self.two_by_two_table.blockSignals(False)

    def cell_changed(self, row, col):
        print "Beginning of cell_changed"
        
        try:
            # Test if entered data is valid (a number)
            warning_msg = self.cell_data_invalid(self.two_by_two_table.item(row, col).text())
            if warning_msg:
                raise Exception("Invalid Cell Data")
    
            self._update_data_table() # calculate rest of table (provisionally) based on new entry
            warning_msg = self.check_table_consistency.run()
            if warning_msg:
                raise Exception("Table no longer consistent.")
        except Exception as e:
            msg = e.args[0]
            QMessageBox.warning(self.parent(), "whoops", msg) #popup warning
            self.restore_form_state() # brings things back to the way they were
            return                    # and leave
        
        # if we got here, everything seems ok
        self.save_form_state()
        self._update_ma_unit()           # 2x2 table --> ma_unit
        self.impute_effects_in_ma_unit() # effects   --> ma_unit
        self.set_current_effect()        # ma_unit   --> effects
        self.enable_back_calculation_btn()
        self.save_form_state()
        
        # disable just-edited cell
        self.block_all_signals(True)
        item = self.two_by_two_table.item(row, col)
        newflags = item.flags() & ~Qt.ItemIsEditable
        item.setFlags(newflags)
        self.block_all_signals(False)
    
        self.enable_txt_box_input() # if the effect was imputed
        self.set_clear_btn_color()
        
    def save_form_state(self):
        ''' Saves the state of all objects on the form '''
        def save_table_data():
            for row in range(3):
                for col in range(3):
                    item = self.two_by_two_table.item(row, col)
                    contents = "" if item is None else item.text()
                    self.table_backup[row][col]=contents
                    
        def save_displayed_effects_data(effect=None):
            print "Saving Displayed Effects data...."
            
            if effect is None:
                effect = self.cur_effect
            
            self.form_effects_dict[effect]["est"]   = self.effect_txt_box.text() 
            self.form_effects_dict[effect]["lower"] = self.low_txt_box.text()    
            self.form_effects_dict[effect]["upper"] = self.high_txt_box.text()    
            self.form_effects_dict["prevalence"] = self.prevalence_txt_box.text() 
        
            self.candidate_est        = self.effect_txt_box.text()
            self.candidate_lower      = self.low_txt_box.text()
            self.candidate_upper      = self.high_txt_box.text()
            self.candidate_prevalence = self.prevalence_txt_box.text()

        save_table_data()
        save_displayed_effects_data()
        self.enable_back_calculation_btn()
    
    def restore_form_state(self):
        ''' Restores the state of all objects on the form '''
        
        # Block all signals on the form 
        self.block_all_signals(True)
        ########################################################################
        
        def restore_displayed_effects_data():
            print "Restoring displayed effects data..."
            
            self.effect_txt_box.setText(    self.form_effects_dict[self.cur_effect]["est"]  )    
            self.low_txt_box.setText(       self.form_effects_dict[self.cur_effect]["lower"])       
            self.high_txt_box.setText(      self.form_effects_dict[self.cur_effect]["upper"])                    
            self.prevalence_txt_box.setText(self.form_effects_dict["prevalence"]            )
            
            self.candidate_est        = self.effect_txt_box.text()
            self.candidate_lower      = self.low_txt_box.text()
            self.candidate_upper      = self.high_txt_box.text()
            self.candidate_prevalence = self.prevalence_txt_box.text()
        
        def restore_table():
            #print "Table to restore:"
            #self.print_backup_table()
        
            for row in range(3):
                for col in range(3):
                    self.two_by_two_table.blockSignals(True)
                    self._set_val(row, col, self.table_backup[row][col])
                    self.two_by_two_table.blockSignals(False)
            self.check_table_consistency.run()
            
            #print("Backed-up table:")
            #self.print_backup_table()
        
        self.CI_spinbox.setValue(meta_py_r.get_global_conf_level())
        restore_displayed_effects_data()
        restore_table()
        self.enable_back_calculation_btn()
        
        
        ########################################################################
        # Unblock the signals
        self.block_all_signals(False)
                    
    
    def getTotalSubjects(self):
        try:
            return int(self.table_backup[2][2])
        except:
            return None

    def print_backup_table(self):
        for row in range(3):
            line = ""
            for col in range(3):
                line += self.table_backup[row][col] + ", "
            print line
    
    def _get_table_vals(self):
        ''' Package table from 2x2 table in to a dictionary'''
        
        vals_d = {}
        vals_d["c11"] = self._get_int(0, 0)
        vals_d["c12"] = self._get_int(0, 1)
        vals_d["c21"] = self._get_int(1, 0)
        vals_d["c22"] = self._get_int(1, 1)
        vals_d["r1sum"] = self._get_int(0, 2)
        vals_d["r2sum"] = self._get_int(1, 2)
        vals_d["c1sum"] = self._get_int(2, 0)
        vals_d["c2sum"] = self._get_int(2, 1)
        vals_d["total"] = self._get_int(2, 2)
        return vals_d
            
    def impute_effects_in_ma_unit(self):
        '''Calculate and store values for effects in ma_unit based on values in 2x2 table'''
        
        # diagnostic data
        counts = self.get_raw_diag_data()
        tp, fn, fp, tn = counts['TP'], counts['FN'], counts['FP'], counts['TN']
        
        # Do what we can if we don't have all the counts
        can_calculate_sens, can_calculate_spec = True, True
        if None in [tp,fn]:
            can_calculate_sens = False
            tp,fn = 0,0 # dummy data
        if None in [tn,fp]:
            can_calculate_spec = False
            tn, fp = 0,0 # dummy data
        
        # sensitivity and specificity
        ests_and_cis = meta_py_r.diagnostic_effects_for_study(
                                tp, fn, fp, tn, metrics=DIAGNOSTIC_METRICS,
                                conf_level=self.CI_spinbox.value())
        
        # now we're going to set the effect estimate/CI on the MA object.
        for metric in DIAGNOSTIC_METRICS:
            # don't set stuff if it made-up
            if metric.lower()=="sens" and not can_calculate_sens:
                continue
            elif metric.lower()=="spec" and not can_calculate_spec:
                continue
            
            est, lower, upper = ests_and_cis[metric]["calc_scale"]
            self.ma_unit.set_effect_and_ci(metric, self.group_str, est, lower, upper)
            disp_est, disp_lower, disp_upper = ests_and_cis[metric]["display_scale"]
            self.ma_unit.set_display_effect_and_ci(metric, self.group_str, disp_est, disp_lower, disp_upper)

    def _get_row_col(self, field):
        row = 0 if field in ("FP", "TP") else 1
        col = 1 if field in ("FP", "TN") else 0
        return (row, col)

    def update_2x2_table(self, imputed_dict):
        ''' Fill in entries in 2x2 table and add data to ma_unit'''
        
        print "Updating 2x2......"
        
        # reset relevant column and sums column if we have new data
        if imputed_dict["TP"] and imputed_dict["FN"]:
            print("TP, FN:", imputed_dict["TP"],imputed_dict["FN"])
            print "clearing col 0 and 2"
            self.clear_column(0)
            self.clear_column(2)
        if imputed_dict["TN"] and imputed_dict["FP"]:
            print "clearing col 1 and 2"
            self.clear_column(1)
            self.clear_column(2)
        
        for field in ["FP", "TP", "TN", "FN"]:
            if (field in imputed_dict) and (not imputed_dict[field] is None):
                row, col = self._get_row_col(field)
                self._set_val(row, col, imputed_dict[field])
                # here we update the MA unit
                raw_data_index = DIAG_FIELDS_TO_RAW_INDICES[field]
                
                # TODO: ENC
                self.ma_unit.tx_groups[self.group_str].raw_data[raw_data_index] =\
                    None if not _is_a_float(imputed_dict[field]) else float(imputed_dict[field])
    
    def _update_ma_unit(self):
        '''Copy data from data table to the MA_unit'''
        
        print "updating ma unit...."
        raw_dict = self.get_raw_diag_data() # values are floats or None
        for field in raw_dict.iterkeys():
            i = DIAG_FIELDS_TO_RAW_INDICES[field]
            self.ma_unit.tx_groups[self.group_str].raw_data[i] = raw_dict[field]  # TODO: ENC
    
    def get_raw_diag_data(self,convert_None_to_NA_string=False):
        '''Returns a dictionary of the raw data in the table (TP,FN,FP,TN), 
           None for empty cell'''
        
        NoneValue = "NA" if convert_None_to_NA_string else None
        
        d={}
        d["TP"] = float(self._get_int(0,0)) if not self._is_empty(0,0) else NoneValue
        d["FN"] = float(self._get_int(1,0)) if not self._is_empty(1,0) else NoneValue
        d["FP"] = float(self._get_int(0,1)) if not self._is_empty(0,1) else NoneValue
        d["TN"] = float(self._get_int(1,1)) if not self._is_empty(1,1) else NoneValue
        return d

    def block_all_signals(self,state):
        for widget in self.entry_widgets:
            widget.blockSignals(state)

    def val_changed(self, val_str):
        print "--------------\nEntering val_changed...."
        
        def is_between_bounds(est=self.form_effects_dict[self.cur_effect]["est"], 
                              low=self.form_effects_dict[self.cur_effect]["lower"], 
                              high=self.form_effects_dict[self.cur_effect]["upper"]):
            return meta_globals.between_bounds(est=est, low=low, high=high)

        ###### ERROR CHECKING CODE#####
        # Make sure entered value is numeric and between the appropriate bounds
        self.block_all_signals(True)
        float_msg = "Must be numeric!"
        try:
            if val_str == "est" and not _is_empty(self.candidate_est):
                # Check type
                if not _is_a_float(self.candidate_est) :
                    QMessageBox.warning(self, "whoops", float_msg)
                    raise Exception("error")
                (good_result,msg) = is_between_bounds(est=self.candidate_est)
                if not good_result:
                    QMessageBox.warning(self, "whoops", msg)
                    raise Exception("error")
                if (not 0 <= float(self.candidate_est) <= 1):
                    QMessageBox.warning(self, "whoops", "Estimate must be between 0 and 1.")
                    raise Exception("error")
                display_scale_val = float(self.candidate_est)
            elif val_str == "lower" and not _is_empty(self.candidate_lower):
                if not _is_a_float(self.candidate_lower) :
                    QMessageBox.warning(self, "whoops", float_msg)
                    raise Exception("error")
                (good_result,msg) = is_between_bounds(low=self.candidate_lower)
                if not good_result:
                    QMessageBox.warning(self, "whoops", msg)
                    raise Exception("error")
                display_scale_val = float(self.candidate_lower)
            elif val_str == "upper" and not _is_empty(self.candidate_upper): 
                if not _is_a_float(self.candidate_upper) :
                    QMessageBox.warning(self, "whoops", float_msg)
                    raise Exception("error")
                (good_result,msg) = is_between_bounds(high=self.candidate_upper)
                if not good_result:
                    QMessageBox.warning(self, "whoops", msg)
                    raise Exception("error")
                display_scale_val = float(self.candidate_upper)
            elif val_str == "prevalence" and not _is_empty(self.candidate_prevalence):
                if not _is_a_float(self.candidate_prevalence):
                    QMessageBox.warning(self, "whoops", float_msg)
                    raise Exception("error")
                if _is_a_float(self.candidate_prevalence) and not 0 < float(self.candidate_prevalence) < 1:
                    QMessageBox.warning(self, "whoops", "Prevalence must be between 0 and 1.")
                    raise Exception("error")
        except:
            print "Error flag is true"
            self.restore_form_state()
            self.block_all_signals(True)
            if val_str == "est":
                self.effect_txt_box.setFocus()
            elif val_str == "lower":
                self.low_txt_box.setFocus()
            elif val_str == "upper":
                self.high_txt_box.setFocus()
            elif val_str == "prevalence":
                self.prevalence_txt_box.setFocus()
            self.block_all_signals(False)
            return
                
        self.block_all_signals(False)
        
        # If we got to this point it means everything is ok so far
        #######self._save_displayed_effects_data()
        
        try:
            display_scale_val = float(display_scale_val)
        except:
            # a number wasn't entered; ignore
            # should probably clear out the box here, too.
            print "fail."
            return None
            
        calc_scale_val = meta_py_r.binary_convert_scale(display_scale_val, \
                                        self.cur_effect, convert_to="calc.scale")
        
        if val_str == "est":
            self.ma_unit.set_effect(self.cur_effect, self.group_str, calc_scale_val)
            self.ma_unit.set_display_effect(self.cur_effect, self.group_str, display_scale_val)
        elif val_str == "lower":
            self.ma_unit.set_lower(self.cur_effect, self.group_str, calc_scale_val)
            self.ma_unit.set_display_lower(self.cur_effect, self.group_str, display_scale_val)
        elif val_str == "upper":
            self.ma_unit.set_upper(self.cur_effect, self.group_str, calc_scale_val)
            self.ma_unit.set_display_upper(self.cur_effect, self.group_str, display_scale_val)
        elif val_str == "prevalence":
            pass

        self.enable_txt_box_input()
        self.save_form_state()
        self.enable_back_calculation_btn()
        
    def val_edit(self, val_str, display_scale_val):
        print "Editing %s with value: %s" % (val_str,display_scale_val)
        if val_str == "est":
            self.candidate_est = display_scale_val
        if val_str == "lower":
            self.candidate_lower = display_scale_val
        if val_str == "upper":
            self.candidate_upper = display_scale_val
        if val_str == "prevalence":
            self.candidate_prevalence = display_scale_val

    def effect_changed(self):
        # Re-scale previous effect first
        self.reset_conf_level()
        
        self.cur_effect = str(self.effect_cbo_box.currentText()) 
        self.set_current_effect()
        
        self.enable_txt_box_input()
        self.enable_back_calculation_btn()
            
    def _read_in_table_data_from_MAunit(self):
        ''' populates the 2x2 table with whatever parametric data was provided '''
        self.two_by_two_table.blockSignals(True) 
        field_index = 0
        for col in (0,1):
            for row in (0,1):
                val = self.raw_data_dict[self.group_str][field_index]
                if val is not None:
                    try:
                        val = str(int(val))
                    except:
                        val = str(val)
                    item = QTableWidgetItem(val)
                    self.two_by_two_table.setItem(row, col, item)
                field_index+=1
        self.two_by_two_table.blockSignals(False)

    def _populate_effect_cmbo_box(self):
        # for now we only back-calculate from sens/spec
        effects = BACK_CALCULATABLE_DIAGNOSTIC_EFFECTS # TODO add more metrics
        self.effect_cbo_box.blockSignals(True)
        self.effect_cbo_box.addItems(effects)
        self.effect_cbo_box.blockSignals(False)
        self.effect_cbo_box.setCurrentIndex(0)
    
    def set_current_effect(self):
        '''Fill in effect text boxes with data from ma_unit'''
        effect_dict = self.ma_unit.effects_dict[self.cur_effect][self.group_str]
        for s, txt_box in zip(['display_est', 'display_lower', 'display_upper'],
                              [self.effect_txt_box, self.low_txt_box, self.high_txt_box]):
            txt_box.blockSignals(True)
            if effect_dict[s] is not None:
                txt_box.setText(QString("%s" % round(effect_dict[s], NUM_DIGITS)))
                print("From set_current effect: %s=%s" %(s, round(effect_dict[s], NUM_DIGITS)))
            else:
                txt_box.setText(QString(""))
            txt_box.blockSignals(False)
    
    def print_effects_dict_from_ma_unit(self):
        print self.ma_unit.get_effects_dict()
            
    def setup_table_effect_dict(self):
        '''Fill in local copy of table-effects dict w/ data from ma_unit'''
        
        print "effects dict from ma unit:"
        self.print_effects_dict_from_ma_unit() 
        
        for effect in BACK_CALCULATABLE_DIAGNOSTIC_EFFECTS:
            effects_dict = self.ma_unit.effects_dict[effect][self.group_str]
            for keyA,keyB in zip(['display_est', 'display_lower', 'display_upper'],["est","lower","upper"]):
                self.form_effects_dict[effect][keyB] = str(effects_dict[keyA])
                
        print "Form effects dict:",self.form_effects_dict

    def _update_data_table(self):
        '''Try to calculate rest of 2x2 table from existing cells'''
        
        self.block_all_signals(True)
        
        params = self._get_table_vals()
        computed_params = meta_globals.compute_2x2_table(params)
        print "Computed Params", computed_params
        if computed_params:
            self._set_vals(computed_params) # computed --> table widget
        
        # Compute prevalence if possible
        if (not computed_params['c1sum'] in EMPTY_VALS) and (not computed_params['total'] in EMPTY_VALS):
            prevalence = float(computed_params['c1sum'])/float(computed_params['total'])
            prev_str = str(prevalence)[:7]
            self.prevalence_txt_box.setText("%s" % prev_str)
            self.enable_txt_box_input()
        
        self.block_all_signals(False)
        
    def clear_column(self,col):
        '''Clears out column in table and ma_unit'''
        
        print("Clearing column %d" % col)
        for row in range(3):
            self._set_val(row, col, None)  
        
        self._update_ma_unit()
        self.save_form_state()
        
    def clear_form(self):
        keys = ["c11", "c12", "r1sum", "c21", "c22", "r2sum", "c1sum", "c2sum", "total"]
        blank_vals = dict( zip(keys, [""]*len(keys)) )

        self._set_vals(blank_vals)
        self._update_ma_unit()
        
        # clear out effects stuff
        for metric in DIAGNOSTIC_METRICS:
            self.ma_unit.set_effect_and_ci(metric, self.group_str, None, None, None)
            self.ma_unit.set_display_effect_and_ci(metric, self.group_str, None, None, None)
            
        # clear line edits
        self.set_current_effect()
        self.prevalence_txt_box.blockSignals(True)
        self.prevalence_txt_box.setText("")
        self.prevalence_txt_box.blockSignals(False)
        
        self.save_form_state()
       
        # reset form_effects_dict (backup)
        self.form_effects_dict = {"Sens":{"est":"","lower":"","upper":"",},
                                  "Spec":{"est":"","lower":"","upper":"",},
                                  "prevalence":""}

        self.reset_table_item_flags()
        self.enable_txt_box_input()
        self.CI_spinbox.setValue(meta_py_r.get_global_conf_level())
        self.CI_spinbox.setEnabled(True)
        
    def enable_txt_box_input(self):
        ''' Enables text boxes if they are empty, disables them otherwise '''
        
        #meta_globals.enable_txt_box_input(self.effect_txt_box, self.low_txt_box,
        #                                  self.high_txt_box, self.prevalence_txt_box)
        pass
           
    def reset_table_item_flags(self):
        self.block_all_signals(True)
        for row in range(3):
            for col in range(3):
                item = self.two_by_two_table.item(row, col)
                if not item is None:
                    newflags = item.flags() | Qt.ItemIsEditable
                    item.setFlags(newflags)
        self.block_all_signals(False)
    
    def input_fields_disabled(self):
        table_disabled = True
        for row in range(3):
            for col in range(3):
                item = self.two_by_two_table.item(row, col)
                if item is None:
                    continue
                if (item.flags() & Qt.ItemIsEditable) == Qt.ItemIsEditable:
                    table_disabled = False
                    
        txt_boxes_disabled = self._txt_boxes_disabled()

        if table_disabled and txt_boxes_disabled:
            self.CI_spinbox.setEnabled(False) # weird place for ?this? but whatever
            return True
        return False
    
    
    def _txt_boxes_disabled(self):
        return not (self.effect_txt_box.isEnabled() or
                    self.low_txt_box.isEnabled() or
                    self.high_txt_box.isEnabled() or
                    self.prevalence_txt_box.isEnabled())
    
    def set_clear_btn_color(self):
        if self.input_fields_disabled():
            self.clear_Btn.setPalette(self.pushme_palette)
        else:
            self.clear_Btn.setPalette(self.orig_palette)
            
    def enable_back_calculation_btn(self, engage = False):
        print("Enabling back-calculation button...")
        
        def build_dict():
            d = {}

            for effect in BACK_CALCULATABLE_DIAGNOSTIC_EFFECTS:
                for key,Rsubkey in zip(["est","lower","upper"],["",".lb",".ub"]):
                    try:
                        d["%s%s" % (effect.lower(), Rsubkey)] = float(self.form_effects_dict[effect][key])
                    except:
                        pass
            
            x = self.getTotalSubjects()
            d["total"] = float(x) if _is_a_float(x) else None

            x = self.prevalence_txt_box.text()
            d["prev"] = float(x) if _is_a_float(x) else None

            x = self.CI_spinbox.value()
            d["conf.level"] = x if _is_a_float(x) else None
    
            # now grab the raw data, if available
            d.update(self.get_raw_diag_data())
            
            return d
        
        def new_data(diag_data, imputed):
            new_data = (imputed["TP"],
                        imputed["FP"],
                        imputed["FN"],
                        imputed["TN"])
            old_data = (self._get_int(0,0),
                        self._get_int(0,1),
                        self._get_int(1,0),
                        self._get_int(1,1),
                        )
            isBlank = lambda x: x in meta_globals.EMPTY_VALS
            new_item_available = lambda old, new: isBlank(old) and not isBlank(new)
            comparison = [new_item_available(old_data[i], new_data[i]) for i in range(len(new_data))]
            print("Comparison:", comparison)
            if any(comparison):
                changed = True
            else:
                changed = False
            return changed
            
        diag_data = build_dict()
        print("Diagnostic Data for back-calculation: ", diag_data)

        #if diag_data is not None:
            
        imputed = meta_py_r.impute_diag_data(diag_data)
        print "imputed data: %s" % imputed
        
        # Leave if nothing was imputed
        if not (imputed["TP"] or imputed["TN"] or imputed["FP"] or imputed["FN"]):
            print("Nothing could be imputed")
            self.back_calc_Btn.setEnabled(False)
            return None
    
        if new_data(diag_data, imputed):
            self.back_calc_Btn.setEnabled(True)
        else:
            self.back_calc_Btn.setEnabled(False)
        self.set_clear_btn_color()
            
        if not engage:
            return None
        ########################################################################
        # Actually do stuff with imputed data here if we are 'engaged'
        ########################################################################
        self.update_2x2_table(imputed)
        self._update_data_table()
        self.save_form_state()
        
        self.set_clear_btn_color()

        # Go backward in case we have a missing effect
        #self.impute_effects_in_ma_unit() 
        #self.set_current_effect()
        #self.save_form_state()

    def change_CI_alert(self,value=None):
        if not self.already_showed_change_CI_alert:
            QMessageBox.information(self, "Changing Confidence Level", meta_globals.get_CHANGE_CI_ALERT_MSG())
            self.already_showed_change_CI_alert = True
    
    # TODO: should be refactored to shared function in meta_globals
    def reset_conf_level(self):
        print("Re-scaling est, low, high to standard confidence level")
        
        old_effect_and_ci = self.ma_unit.get_effect_and_ci(self.cur_effect, self.group_str)
        
        argument_d = {"est"  : old_effect_and_ci[0],
                      "low"  : old_effect_and_ci[1],
                      "high" : old_effect_and_ci[2],
                      "orig.conf.level": self.CI_spinbox.value(),
                      "target.conf.level": meta_py_r.get_global_conf_level()}
        
        res = meta_py_r.rescale_effect_and_ci_conf_level(argument_d)
        if "FAIL" in res:
            print("Could not reset confidence level")
            return
        
        res["display_est"]  = meta_py_r.diagnostic_convert_scale(res["est"], self.cur_effect, convert_to="display.scale")
        res["display_low"]  = meta_py_r.diagnostic_convert_scale(res["low"], self.cur_effect, convert_to="display.scale")
        res["display_high"] = meta_py_r.diagnostic_convert_scale(res["high"], self.cur_effect, convert_to="display.scale")
        
        # Save results in ma_unit
        self.ma_unit.set_effect_and_ci(self.cur_effect, self.group_str, res["est"],res["low"],res["high"])
        self.ma_unit.set_display_effect_and_ci(self.cur_effect, self.group_str, res["display_est"],res["display_low"],res["display_high"])
Example #30
0
	def __init__(self):
		super(StartGui, self).__init__()

		self.ui = Ui_MainWindow()
		self.ui.setupUi(self)
		self.setWindowTitle(Title)

		self.ui.btn_Compilar.setEnabled(False)
		self.ui.btn_Ejecutar.setEnabled(False)

		### Elementos del menu ###############################################
		#### ARCHIVO ####
		nuevo_ = QAction('Nuevo', self)
		nuevo_.setShortcut("Ctrl+n")
		self.connect(nuevo_, QtCore.SIGNAL("triggered()"), self.func_nuevo)

		abrir = QAction('Abrir archivo', self)
		abrir.setShortcut("Ctrl+o")
		self.connect(abrir, QtCore.SIGNAL("triggered()"), self.func_abrir)

		guardar_ = QAction('Guardar', self)
		guardar_.setShortcut("Ctrl+s")
		self.connect(guardar_, QtCore.SIGNAL("triggered()"), self.func_guardar)

		salir_ = QAction('Salir de SIDE', self)
		self.connect(salir_, QtCore.SIGNAL("triggered()"), self.close)


		#### AYUDA ####
		about_side = QAction('Acerca de SIDE', self)
		self.connect(about_side, QtCore.SIGNAL("triggered()"), self.aboutSide)

		menubar = self.menuBar()
		filemenu = menubar.addMenu("&Archivo")
		filemenu.addAction(nuevo_)
		filemenu.addAction(abrir)
		filemenu.addAction(guardar_)
		filemenu.addSeparator()
		filemenu.addAction(salir_)
		helpmenu = menubar.addMenu("Ayuda")
		helpmenu.addAction(about_side)
		helpmenu.addAction('About Qt', QtGui.qApp.aboutQt)
		########################################################################

		font = QtGui.QFont("Ubuntu Mono")
		font.setPointSize(12)
		self.ui.textEdit.setFont(font)

		Sintaxis(self.ui.textEdit, "Classic")


		# Color QTextEdit
		paleta = QPalette()
		color = QColor(30, 30, 30)
		paleta.setColor(QPalette.Base, color)
		# Color Texto
		color_Text = QColor(200, 200, 200)
		paleta.setColor(QPalette.Text, color_Text)
		self.setPalette(paleta)

		# Botones
		# Boton salir
		self.connect(self.ui.btn_Salir, QtCore.SIGNAL("clicked()"), self.close)
		self.ui.btn_Salir.setToolTip("Salir de SIDE")

		# Boton Nuevo
		self.connect(self.ui.btn_Nuevo, QtCore.SIGNAL("clicked()"), self.func_nuevo)
		self.ui.btn_Nuevo.setToolTip("Nuevo archivo")

		# Boton Abrir
		self.connect(self.ui.btn_Abrir, QtCore.SIGNAL("clicked()"), self.func_abrir)
		self.ui.btn_Abrir.setToolTip("Abrir archivo")

		# Boton Guardar
		self.connect(self.ui.btn_Guardar, QtCore.SIGNAL("clicked()"), self.func_guardar)
		self.ui.btn_Guardar.setToolTip("Guardar archio actual")

		self.ui.btn_Guardar.setEnabled(False)
Example #31
0
 def set_cg_color(self, val):
     pal = QPalette()
     pal.setColor(QPalette.Window, QColor(*val))
     self.cover_grid_color_label.setPalette(pal)
    def initialize(self, parent, content, book_id, installed_book, marvin_db_path, use_qwv=True):
        '''
        __init__ is called on SizePersistedDialog()
        '''
        self.setupUi(self)
        self.book_id = book_id
        self.connected_device = parent.opts.gui.device_manager.device
        self.installed_book = installed_book
        self.marvin_db_path = marvin_db_path
        self.opts = parent.opts
        self.parent = parent
        self.stored_command = None
        self.verbose = parent.verbose
        self._log_location(installed_book.title)

        # Subscribe to Marvin driver change events
        self.connected_device.marvin_device_signals.reader_app_status_changed.connect(
            self.marvin_status_changed)

        # Set the icon
        self.setWindowIcon(self.parent.icon)

        # Set or hide the header
        if content['header']:
            self.header.setText(content['header'])
        else:
            self.header.setVisible(False)

        # Set the titles
        self.setWindowTitle(content['title'])
        self.html_gb.setTitle(content['group_box_title'])
        if content['toolTip']:
            self.html_gb.setToolTip(content['toolTip'])

        # Set the bg color of the content to the dialog bg color
        bgcolor = self.palette().color(QPalette.Background)
        palette = QPalette()
        palette.setColor(QPalette.Base, bgcolor)

        #self._log(repr(content['html_content']))

        # Initialize the window content
        if use_qwv:
            # Add a QWebView to layout
            self.html_wv = QWebView()
            self.html_wv.setHtml(content['html_content'])
            self.html_wv.sizeHint = self.wv_sizeHint
            self.html_wv.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
            self.html_wv.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
            self.html_wv.linkClicked.connect(self.link_clicked)

            self.html_gb_vl.addWidget(self.html_wv)
            self.html_tb.setVisible(False)
        else:
            # Initialize the contents of the TextBrowser
            self.html_tb.setText(content['html_content'])
            #self.html_tb.setPalette(palette)

        # Set or hide the footer
        if content['footer']:
            self.footer.setText(content['footer'])
        else:
            self.footer.setVisible(False)

        # Add Copy to Clipboard button
        self.ctc_button = self.bb.addButton('&Copy to clipboard',
                                            self.bb.ActionRole)
        self.ctc_button.clicked.connect(self.copy_to_clipboard)
        self.ctc_button.setIcon(QIcon(I('edit-copy.png')))
        self.ctc_button.setObjectName('copy_to_clipboard_button')
        self.ctc_button.setToolTip('<p>Copy plain text to clipboard, <b>Alt/Option-click</b> for HTML</p>')

        self.copy_action = QAction(self)
        self.addAction(self.copy_action)
        self.copy_action.setShortcuts(QKeySequence.Copy)
        self.copy_action.triggered.connect(self.copy_to_clipboard)

        # Add Refresh button if enabled
        if content['refresh']:
            self.refresh_method = content['refresh']['method']
            self.refresh_button = self.bb.addButton("Refresh '%s'" % content['refresh']['name'],
                                                    self.bb.ActionRole)
            self.refresh_button.setIcon(QIcon(os.path.join(self.parent.opts.resources_path,
                                              'icons',
                                              'from_marvin.png')))
            self.refresh_button.setObjectName('refresh_button')
            self.refresh_button.setEnabled(bool(self.installed_book.cid))

        # Hook the button events
        self.bb.clicked.connect(self.dispatch_button_click)

        # Restore position
        self.resize_dialog()
    def initialize(self,
                   parent,
                   content,
                   book_id,
                   installed_book,
                   marvin_db_path,
                   use_qwv=True):
        '''
        __init__ is called on SizePersistedDialog()
        '''
        self.setupUi(self)
        self.book_id = book_id
        self.connected_device = parent.opts.gui.device_manager.device
        self.installed_book = installed_book
        self.marvin_db_path = marvin_db_path
        self.opts = parent.opts
        self.parent = parent
        self.stored_command = None
        self.verbose = parent.verbose
        self._log_location(installed_book.title)

        # Subscribe to Marvin driver change events
        self.connected_device.marvin_device_signals.reader_app_status_changed.connect(
            self.marvin_status_changed)

        # Set the icon
        self.setWindowIcon(self.parent.icon)

        # Set or hide the header
        if content['header']:
            self.header.setText(content['header'])
        else:
            self.header.setVisible(False)

        # Set the titles
        self.setWindowTitle(content['title'])
        self.html_gb.setTitle(content['group_box_title'])
        if content['toolTip']:
            self.html_gb.setToolTip(content['toolTip'])

        # Set the bg color of the content to the dialog bg color
        bgcolor = self.palette().color(QPalette.Background)
        palette = QPalette()
        palette.setColor(QPalette.Base, bgcolor)

        #self._log(repr(content['html_content']))

        # Initialize the window content
        if use_qwv:
            # Add a QWebView to layout
            self.html_wv = QWebView()
            self.html_wv.setHtml(content['html_content'])
            self.html_wv.sizeHint = self.wv_sizeHint
            self.html_wv.setSizePolicy(QSizePolicy.MinimumExpanding,
                                       QSizePolicy.MinimumExpanding)
            self.html_wv.page().setLinkDelegationPolicy(
                QWebPage.DelegateAllLinks)
            self.html_wv.linkClicked.connect(self.link_clicked)

            self.html_gb_vl.addWidget(self.html_wv)
            self.html_tb.setVisible(False)
        else:
            # Initialize the contents of the TextBrowser
            self.html_tb.setText(content['html_content'])
            #self.html_tb.setPalette(palette)

        # Set or hide the footer
        if content['footer']:
            self.footer.setText(content['footer'])
        else:
            self.footer.setVisible(False)

        # Add Copy to Clipboard button
        self.ctc_button = self.bb.addButton('&Copy to clipboard',
                                            self.bb.ActionRole)
        self.ctc_button.clicked.connect(self.copy_to_clipboard)
        self.ctc_button.setIcon(QIcon(I('edit-copy.png')))
        self.ctc_button.setObjectName('copy_to_clipboard_button')
        self.ctc_button.setToolTip(
            '<p>Copy plain text to clipboard, <b>Alt/Option-click</b> for HTML</p>'
        )

        self.copy_action = QAction(self)
        self.addAction(self.copy_action)
        self.copy_action.setShortcuts(QKeySequence.Copy)
        self.copy_action.triggered.connect(self.copy_to_clipboard)

        # Add Refresh button if enabled
        if content['refresh']:
            self.refresh_method = content['refresh']['method']
            self.refresh_button = self.bb.addButton(
                "Refresh '%s'" % content['refresh']['name'],
                self.bb.ActionRole)
            self.refresh_button.setIcon(
                QIcon(
                    os.path.join(self.parent.opts.resources_path, 'icons',
                                 'from_marvin.png')))
            self.refresh_button.setObjectName('refresh_button')
            self.refresh_button.setEnabled(bool(self.installed_book.cid))

        # Hook the button events
        self.bb.clicked.connect(self.dispatch_button_click)

        # Restore position
        self.resize_dialog()