Exemple #1
0
class Cell(QGraphicsPolygonItem, Item):
    "Hexagonal cell"
    unknown = Entity('Cell.unknown')
    empty = Entity('Cell.empty')
    full = Entity('Cell.full')
    
    def __init__(self):
        QGraphicsPolygonItem.__init__(self, _cell_outer)
        
        self._inner = QGraphicsPolygonItem(_cell_inner)
        self._inner.setPen(no_pen)

        pen = QPen(Color.border, 0.03)
        pen.setJoinStyle(qt.MiterJoin)
        self.setPen(pen)

        self._text = QGraphicsSimpleTextItem('{?}')
        self._text.setBrush(Color.light_text)
        update_font(self._text, lambda f: f.setWeight(55))
        
        self._extra_text = QGraphicsSimpleTextItem('')
        
        self.kind = Cell.unknown
        self.show_info = 0

    @property
    def display(self):
        return self.kind
    
    @cached_property
    def neighbors(self):
        return list(self._find_neighbors(_neighbors_deltas, Cell))
    @cached_property
    def flower_neighbors(self):
        return list(self._find_neighbors(_flower_deltas, Cell))
    @cached_property
    def columns(self):
        result = []
        for col in self._find_neighbors(_columns_deltas, Column):
            sgn = col.angle//60
            if sgn == col.coord.x-self.coord.x:
                result.append(col)
        return result
    
    @cached_property
    def members(self):
        if self.show_info:
            if self.kind is Cell.empty:
                return self.neighbors
            if self.kind is Cell.full:
                return self.flower_neighbors

    def is_neighbor(self, other):
        return other in self.neighbors

    @cached_property
    def value(self):
        if self.show_info:
            return sum(1 for it in self.members if it.kind is Cell.full)
    
    @cached_property
    def together(self):
        if self.show_info == 2:
            full_items = {it for it in self.members if it.kind is Cell.full}
            return all_grouped(full_items, key=Cell.is_neighbor)

    def reset_cache(self):
        for attr in ['neighbors', 'flower_neighbors', 'columns', 'members', 'value', 'together']:
            try:
                delattr(self, attr)
            except AttributeError: pass
    
    @property
    def extra_text(self):
        return self._extra_text.text().replace('\n', '')
    @extra_text.setter
    def extra_text(self, value):
        value = value[:3]
        self._extra_text.setText(value)
        self.upd()
    
    def keyPressEvent(self, e):
        for c in e.text():
            c = c.upper()
            if c.isdigit() or e.modifiers() & (qt.ShiftModifier):
                if c not in ['Q', 'W']:
                    self.extra_text += c
        if e.key() in [qt.Key_Backspace, qt.Key_QuoteLeft, qt.Key_AsciiTilde] or\
          e.text() in [u'`', u'~', u'^', u'\\', u'\N{SECTION SIGN}']:
            if not (e.modifiers() & qt.ShiftModifier):
                self.guess = None
                self.extra_text = ''
    
    def upd(self, first=False):
        self.reset_cache()
        
        if self.display is Cell.unknown:
            self.setBrush(Color.yellow_border)
            self._inner.setBrush(Color.yellow)
            self._text.setText('')
        elif self.display is Cell.empty:
            self.setBrush(Color.black_border)
            self._inner.setBrush(Color.black)
        elif self.display is Cell.full:
            self.setBrush(Color.blue_border)
            self._inner.setBrush(Color.blue)
        
        if not self.placed:
            return
        
        if self.display is not Cell.unknown and self.value is not None:
            txt = str(self.value)
            if self.together is not None:
                txt = ('{{{}}}' if self.together else '-{}-').format(txt)
        else:
            txt = '?' if self.display is Cell.empty else ''
        
        self._text.setText(txt)
        if txt:
            fit_inside(self, self._text, 0.48)
        
        if self.extra_text:
            unknown = self.display is Cell.unknown
            fit_inside(self, self._extra_text, 0.31)
            self._extra_text.setPos(self._extra_text.pos() + QPointF(0, -0.2))
            self._extra_text.setBrush(Color.dark_text if unknown else Color.light_text)
        
        if txt and self.extra_text:
            self._text.setPos(self._text.pos() + QPointF(0, 0.1))

        self.update()
        
        if first:
            with self.upd_neighbors():
                pass
    
    @contextlib.contextmanager
    def upd_neighbors(self):
        neighbors = list(self.flower_neighbors)
        scene = self.scene()
        yield
        for it in neighbors:
            it.upd()
        for it in scene.all(Column):
            it.upd()
    
    def paint(self, g, option, widget):
        QGraphicsPolygonItem.paint(self, g, option, widget)
        self._inner.paint(g, option, widget)
        transform = g.transform()
        g.setTransform(self._extra_text.sceneTransform(), True)
        self._extra_text.paint(g, option, widget)
        g.setTransform(transform)
        g.setTransform(self._text.sceneTransform(), True)
        g.setOpacity(self._text.opacity())
        self._text.paint(g, option, widget)
    
    def __repr__(self, first=True):
        r = [self.display]
        if self.display!=self.kind:
            r.append('({})'.format(repr(self.kind).split('.')[1]))
        r.append(self._text.text())
        try:
            r.append('#{}'.format(self.id))
        except AttributeError: pass
        if first:
            r.append('neighbors:[{}]'.format(' '.join(m.__repr__(False) for m in self.neighbors)))
            if self.members:
                r.append('members:[{}]'.format(' '.join(m.__repr__(False) for m in self.members)))
        return '<{}>'.format(' '.join(str(p) for p in r if str(p)))
Exemple #2
0
class Cell(QGraphicsPolygonItem, Item):
    "Hexagonal cell"
    unknown = Entity('Cell.unknown')
    empty = Entity('Cell.empty')
    full = Entity('Cell.full')
    
    def __init__(self):
        QGraphicsPolygonItem.__init__(self, _cell_outer)
        
        self._inner = QGraphicsPolygonItem(_cell_inner)
        self._inner.setPen(no_pen)

        pen = QPen(Color.border, 0.03)
        pen.setJoinStyle(qt.MiterJoin)
        self.setPen(pen)

        self._text = QGraphicsSimpleTextItem('{?}')
        self._text.setBrush(Color.light_text)
        update_font(self._text, lambda f: f.setWeight(55))
        
        self._extra_text = QGraphicsSimpleTextItem('')
        
        self.kind = Cell.unknown
        self.show_info = 0

    @property
    def display(self):
        return self.kind
    
    @cached_property
    def neighbors(self):
        return list(self._find_neighbors(_neighbors_deltas, Cell))
    @cached_property
    def flower_neighbors(self):
        return list(self._find_neighbors(_flower_deltas, Cell))
    @cached_property
    def columns(self):
        result = []
        for col in self._find_neighbors(_columns_deltas, Column):
            sgn = col.angle//60
            if sgn == col.coord.x-self.coord.x:
                result.append(col)
        return result
    
    @cached_property
    def members(self):
        if self.show_info:
            if self.kind is Cell.empty:
                return self.neighbors
            if self.kind is Cell.full:
                return self.flower_neighbors

    def is_neighbor(self, other):
        return other in self.neighbors

    @cached_property
    def value(self):
        if self.show_info:
            return sum(1 for it in self.members if it.kind is Cell.full)
    
    @cached_property
    def together(self):
        if self.show_info == 2:
            full_items = {it for it in self.members if it.kind is Cell.full}
            return all_grouped(full_items, key=Cell.is_neighbor)

    def reset_cache(self):
        for attr in ['neighbors', 'flower_neighbors', 'columns', 'members', 'value', 'together']:
            try:
                delattr(self, attr)
            except AttributeError: pass
    
    @property
    def extra_text(self):
        return self._extra_text.text().replace('\n', '')
    @extra_text.setter
    def extra_text(self, value):
        value = value[:3]
        self._extra_text.setText(value)
        self.upd()
    
    def keyPressEvent(self, e):
        for c in e.text():
            c = c.upper()
            if c.isdigit() or e.modifiers() & (qt.ShiftModifier):
                if c not in ['Q', 'W']:
                    self.extra_text += c
        if e.key() in [qt.Key_Backspace, qt.Key_QuoteLeft, qt.Key_AsciiTilde] or\
          e.text() in [u'`', u'~', u'^', u'\\', u'\N{SECTION SIGN}']:
            if not (e.modifiers() & qt.ShiftModifier):
                self.guess = None
                self.extra_text = ''
    
    def upd(self, first=False):
        self.reset_cache()
        
        if self.display is Cell.unknown:
            self.setBrush(Color.yellow_border)
            self._inner.setBrush(Color.yellow)
            self._text.setText('')
        elif self.display is Cell.empty:
            self.setBrush(Color.black_border)
            self._inner.setBrush(Color.black)
        elif self.display is Cell.full:
            self.setBrush(Color.blue_border)
            self._inner.setBrush(Color.blue)
        
        if not self.placed:
            return
        
        if self.display is not Cell.unknown and self.value is not None:
            txt = str(self.value)
            if self.together is not None:
                txt = ('{{{}}}' if self.together else '-{}-').format(txt)
        else:
            txt = '?' if self.display is Cell.empty else ''
        
        self._text.setText(txt)
        if txt:
            fit_inside(self, self._text, 0.48)
        
        if self.extra_text:
            unknown = self.display is Cell.unknown
            fit_inside(self, self._extra_text, 0.31)
            self._extra_text.setPos(self._extra_text.pos() + QPointF(0, -0.2))
            self._extra_text.setBrush(Color.dark_text if unknown else Color.light_text)
        
        if txt and self.extra_text:
            self._text.setPos(self._text.pos() + QPointF(0, 0.1))

        self.update()
        
        if first:
            with self.upd_neighbors():
                pass
    
    @contextlib.contextmanager
    def upd_neighbors(self):
        neighbors = list(self.flower_neighbors)
        scene = self.scene()
        yield
        for it in neighbors:
            it.upd()
        for it in scene.all(Column):
            it.upd()
    
    def paint(self, g, option, widget):
        QGraphicsPolygonItem.paint(self, g, option, widget)
        self._inner.paint(g, option, widget)
        transform = g.transform()
        g.setTransform(self._extra_text.sceneTransform(), True)
        self._extra_text.paint(g, option, widget)
        g.setTransform(transform)
        g.setTransform(self._text.sceneTransform(), True)
        g.setOpacity(self._text.opacity())
        self._text.paint(g, option, widget)
    
    def __repr__(self, first=True):
        r = [self.display]
        if self.display!=self.kind:
            r.append('({})'.format(repr(self.kind).split('.')[1]))
        r.append(self._text.text())
        try:
            r.append('#{}'.format(self.id))
        except AttributeError: pass
        if first:
            r.append('neighbors:[{}]'.format(' '.join(m.__repr__(False) for m in self.neighbors)))
            if self.members:
                r.append('members:[{}]'.format(' '.join(m.__repr__(False) for m in self.members)))
        return '<{}>'.format(' '.join(str(p) for p in r if str(p)))