text:
Jeff Bartlett
Chattanooga Head Race
Saturday / October 10 / Ross' Landing / 7:30am
The view of the racers from Walnut Street Bridge is one of the best you can get. Cameron Flanders
RiverRocks outdoor events continue bright and early Saturday, October 10th at 7:30am as the Chattanooga Head Race gets underway at 9:00am and goes on until about 5:00pm. Over 1,600 rowers from around the Southeast converge on the riverfront to represent their crews, their clubs, and their schools. The best vantage point for the Head Race is the Walnut Street Bridge, where you can see the course for two miles upriver. You can also bike, walk, or run to points on the Riverwalk and see the event, or go to the finish line by Ross' Landing. Because each race is a time trial between boats and teams in the same class, the Head Race is an exciting and memorable event.
Lula Lake 5 Points 50
Saturday / October 10 / Lula Lake Land Trust / 8am
Thomas Turner racing through a section of water at the 2014 5-Points 50 Jeff Bartlett
If you're wanting to get out of the city and into the woods Saturday morning, October 10th, head to the Lula Lake Land Trust for the 8:00am start of the Lula Lake 5 Points 50. Combining some of the sweetest singletrack in the country, with short paved sections, multi-use trails and hills, turns, switchbacks, and climbs, this challenging long-distance race is already a classic.
Swim the Suck 10 Mile
Saturday / October 10 / Suck Creek Boat Launch / 8am
An aerial view of the 2014 Swim the Suck Swim the Suck
Swim the Suck , hosted by The Chattanooga Open Water Swimmers and Outdoor Chattanooga gets underway on Saturday, October 10 at 8am. The start is at the Suck Creek Boat Launch on U.S. 27 South/1907 Suck Creek Road. There's a gravel lot with plenty of parking for spectators who can then follow swimmers downriver. There are several locations on Mullins Cove Road, most notably the Pot House, where spectators can park and hike down along the river trail and watch swimmers go by. The race ends at Living Water, and then the after party begins.
High Point Speed Climb
Saturday / October 10 / High Point Climbing and Fitness / 3pm
High Point Climbing and Fitness
If you're looking for something fun and challenging to fill up your Saturday afternoon, High Point's Speed Climbing competition gets underway at 3pm. The competition is open to everyone, so you can try your skill on two fun speed routes on the Upper Deck and two 15 Meter IFSC speed routes on the Lower Deck Speed Walls.
Urban/Nature 10k
Sunday / October 11 / Coolidge Park / 8am
A lone racer near Stringers Ridge Ry Glover
Mix the best of road running and trail running with the Urban/Nature 10K on Sunday, October 11th at 8am. The race starts and finishes at the scenic juncture of Coolidge Park and Renaissance Park under the Market Street bridge. Runners enjoy river views, as well as wetlands and interesting trails before heading into a bungalow-filled neighborhood and the urban trails of Stringers Ridge . Catching the finish from the twin hills at Renaissance Park is about as exciting as it gets for spectators!
Creating Local Flavor: Chattanooga's Emerging Culinary Scene
by EGG Gallery RootsRated
Challenge Yourself on Six of the Steepest Ski Runs in Park City
by RootsRated
How to Have an Unforgettable Multi-Sport Weekend in Greater Palm Springs
by Amanda Itria
The Beast of the East: StumpJump 50K
8 Off-the-Beaten-Path Adventures in Virginia's Shenandoah County
by Malee Baker Oot


text:
António Henrique Rodrigo de Oliveira Marques (ur. 23 sierpnia 1933 roku w São Pedro do Estoril, zm. 23 stycznia 2007 roku w Lizbonie) – portugalski historyk.

Wykształcenie
Uczęszczał do liceum Camões e Gil Vicente w Lizbonie, następnie studiował historię i filozofię na Uniwersytecie Lizbońskim. Po magisterium odbył staż na Uniwersytecie w Würzburgu w Niemczech. W 1960 roku doktoryzował się na podstawie dysertacji na temat stosunków między miastami Hanzy a Portugalią w średniowiecznej Europie.

Praca zawodowa
Od 1956 roku był asystentem na macierzystej uczelni, po doktoracie objął stanowisko adiunkta, które utracił w 1962 roku w związku z poparciem strajków studenckich przeciwko rządowi Salazara. Od 1965 przebywał w Stanach Zjednoczonych, gdzie wykładał na kilku uniwersytetach i w instytucjach kulturalnych, między innymi: w Auburn, na Florydzie, na Universytecie Columbia, w Minnesocie i w Chicago. Powrócił do Portugalii po pięciu latach, jednak pracę akademicką rozpoczął dopiero po rewolucji goździków w 1974 roku. Od 1974 przez dwa lata był również dyrektorem Biblioteki Narodowej w Lizbonie. W 1976 roku został profesorem na powstałym po rewolucji Universidade Nova de Lisboa. Był tam twórcą i do połowy lat 80. przewodniczącym wydziału nauk społecznych. W 1980 roku z jego inicjatywy powołano również Centrum Studiów Historycznych. Jest autorem ponad 50 książek. Jako historyk koncentrował się na średniowieczu, portugalskiej Pierwszej Republice i masonerii. W Polsce najbardziej znany jest z dwutomowej "Historii Portugalii" opublikowanej po polsku w 1987 roku.

Odznaczenia
 Wielki Krzyż Orderu Wolności (1988);
Doktor honoris causa Uniwersytetu La Trobe w Australii (1997).

Upamiętnienie
Istniejące od 1969 roku Stowarzyszenie Hiszpańsko–Portugalskich Studiów Historycznych przyznaje nagrodę jego imienia za prace naukowe na temat historii Portugalii publikowane w językach portugalskim, angielskim, hiszpańskim, katalońskim, włoskim i francuskim.

Przypisy

Portugalscy historycy
Urodzeni w 1933
Zmarli w 2007
Portugalscy wolnomularze
Ludzie związani z Lizboną
Mediewiści

redpajama_set_name: RedPajamaWikipedia


text:
Nov 1, 2019 6:32PM PT
Lady Gaga to Star as 'Black Widow' Who Contracted Murder of Gucci Heir in New Movie
By Claudia Miller
Claudia Miller
More Stories By Claudia
11 Men's Work Boots for Safety & Style
Dua Lipa's Disco Ball Skirt & Electric Blue Heels Will Make You Miss Your Party Days
CREDIT: Matt Baron/Shutterstock
Lady Gaga is set to star in Ridley Scott's new movie depicting the Gucci family dynasty and the murder of Maurizio Gucci, the grandson of the brand's founder, Guccio Gucci.
According to Variety, Gaga will play Maurizio's ex-wife Patrizia Reggiani, who was found guilty of orchestrating her ex-husband's assassination in 1995.
Lady Gaga on the Oscars red carpet.
Patrizia Reggiani in the 1980s.
Maurizio left Reggiani after 12 years for a younger woman, sparking her motivation, among other reasons, for his murder; she served 18 years in prison and was released in 2016, earning her the infamous nickname Black Widow.
Lady Gaga wore Sergio Rossi lace-up booties and a Gucci handbag, 2017.
CREDIT: Splash News
The script will be based on Sara Gay Forden's book "The House of Gucci: A Sensational Story of Murder, Madness, Glamour and Greed."
Scott is known for his work on "The Martian," "Thelma and Louise," "Blade Runner" and many more major hit productions.
In an interview with FN in 2016, Patricia Gucci, love child of the Italian luxury label's designer Aldo Gucci and his lover Bruna Palombo, reflected on the significance of the Gucci loafer: "At the Metropolitan Museum, they showed the Gucci loafer — one of the best shoes that withstood the test of time, and everyone has a memory of that shoe. I had my first pair and they had an incredible quality — there was nothing about a Gucci shoe that cannot handle wear and tear beautifully."
Lady Gaga Glistens in Sparkly Gown & 7-Inch Heels at Makeup Launch
Lady Gaga's Back in Her Favorite 10-Inch Spike Heel Fetish Boots
Lady Gaga Spotlights Upcoming Designer in Chic Leather Ensemble & 10-Inch Heels for Apollo Theater Show

redpajama_set_name: RedPajamaCommonCrawl


text:
from python_qt_binding.QtCore import Qt, QMimeData, QPoint, QEvent
from python_qt_binding.QtGui import QPen, QColor, QSizePolicy, QDrag, QBrush, QGraphicsWidget
from python_qt_binding.QtGui import QGraphicsView, QGraphicsAnchorLayout, QGraphicsScene
from python_qt_binding.QtGui import QFontMetrics, QToolTip, QPixmap, QImage, QPolygon
from python_qt_binding.QtCore import pyqtSignal as Signal

from diarc.snapkey import gen_snapkey, parse_snapkey
from diarc.util import typecheck, TypedDict
from diarc.view import View
from diarc.view import BlockItemAttributes
from diarc.view import BandItemAttributes
from diarc.view import SnapItemAttributes
from .SpacerContainer import SpacerContainer
import json
import sys
import logging

log = logging.getLogger('diarc.qt_view')

class QtBlockItemAttributes(BlockItemAttributes):
    def __init__(self):
        BlockItemAttributes.__init__(self)
        self.__bgcolor = "black"
        self.__border_color = "black"
        self.__label_color = "black"
        self.border_width = 1
    @property
    def bgcolor(self):
        return QColor(self.__bgcolor)
    @bgcolor.setter
    def bgcolor(self, value):
        self.__bgcolor = value
    @property
    def border_color(self):
        return QColor(self.__border_color)
    @border_color.setter
    def border_color(self, value):
        self.__border_color = value
    @property
    def label_color(self):
        return QColor(self.__label_color)
    @label_color.setter
    def label_color(self, value):
        self.__label_color = value

class QtBandItemAttributes(BandItemAttributes):
    def __init__(self):
        BandItemAttributes.__init__(self)
        self._bgcolor = "black"
        self._border_color = "black"
        self._label_color = "black"
    @property
    def bgcolor(self):
        return QColor(self._bgcolor)
    @bgcolor.setter
    def bgcolor(self, value):
        self._bgcolor = value
    @property
    def border_color(self):
        return QColor(self._border_color)
    @border_color.setter
    def border_color(self, value):
        self._border_color = value
    @property
    def label_color(self):
        return QColor(self._label_color)
    @label_color.setter
    def label_color(self, value):
        self._label_color = value

class QtSnapItemAttributes(SnapItemAttributes):
    def __init__(self):
        SnapItemAttributes.__init__(self)
        self._bgcolor = "white"
        self._border_color = "black"
        self._label_color = "black"
    @property
    def bgcolor(self):
        return QColor(self._bgcolor)
    @bgcolor.setter
    def bgcolor(self, value):
        self._bgcolor = value
    @property
    def border_color(self):
        return QColor(self._border_color)
    @border_color.setter
    def border_color(self, value):
        self._border_color = value
    @property
    def label_color(self):
        return QColor(self._label_color)
    @label_color.setter
    def label_color(self, value):
        self._label_color = value

class BandStack(SpacerContainer):
    def __init__(self, parent):
        super(BandStack, self).__init__(parent)
        self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred))
        self.setMinimumWidth(15)
        self.spacerType = BandSpacer

class BandSpacer(SpacerContainer.Spacer):
    def __init__(self, parent):
        super(BandSpacer, self).__init__(parent)
        self._layout_manager = parent.parent
        self._view = parent.parent.view()
        self._adapter = parent.parent.adapter()
        self.dragOver = False
        self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding))
        self.setPreferredHeight(15)
        self.setMinimumHeight(15)
        self.setAcceptDrops(True)

    def _release(self):
        topAltitude = self.topBand.altitude if self.topBand else None
        bottomAltitude = self.bottomBand.altitude if self.bottomBand else None
        log.debug("... Releasing BandSpacer between topBand %r and botBand %r"%(topAltitude, bottomAltitude))
        super(BandSpacer, self)._release()

    @property
    def topBand(self):
        return self.itemA

    @property
    def bottomBand(self):
        return self.itemB

    def link(self):
        l = self.layout()
        # Link To your Top! If you have a band above, connect
        if self.topBand:
            l.addAnchor(self, Qt.AnchorTop, self.topBand, Qt.AnchorBottom)
        # Otherwise, if it is a positive band, connect to the top of the BandStack
        elif self.bottomBand.isPositive():
            l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
        # Otherwise, if it is a negative band, connect to Block Container
        elif not self.bottomBand.isPositive():
            l.addAnchor(self, Qt.AnchorTop, self._layout_manager.block_container, Qt.AnchorBottom)

        # Link to your bottom! If you have a band below, connect
        if self.bottomBand:
            l.addAnchor(self, Qt.AnchorBottom, self.bottomBand, Qt.AnchorTop)
        # Otherwise, if it is a positive band, connect to the block ribbon
        elif self.topBand.isPositive():
            l.addAnchor(self, Qt.AnchorBottom, self._layout_manager.block_container, Qt.AnchorTop)
        elif not self.topBand.isPositive():
            l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)

        # Connect sides
        l.addAnchor(self, Qt.AnchorLeft, self.parent, Qt.AnchorLeft)
        l.addAnchor(self, Qt.AnchorRight, self.parent, Qt.AnchorRight)

    def dragEnterEvent(self,event):
        if not event.mimeData().hasText():
            event.setAccepted(False)
            return
        data = json.loads(str(event.mimeData().text()))
        if not 'band' in data:
            event.setAccepted(False)
            return
        # To know if the band being dragged is on the same side of the blockRibbon,
        # we look at the altitudes of the bands on either side of the spacer.
        # We need to look at both because neither is guarenteed to be a real band
        # (the furthest and closest bands to the blockRibbon will each have a
        # non existant band on one side).
        topAltitude = self.topBand.altitude if self.topBand else 0
        bottomAltitude = self.bottomBand.altitude if self.bottomBand else 0
        # Don't let bands get dragged to adjacent spots (it results in non movement)
        if data['band'] in [topAltitude, bottomAltitude]:
            event.setAccepted(False)
            return
        # Accept a positive altitude band
        if data['band'] > 0 and (topAltitude > 0 or bottomAltitude > 0):
            event.setAccepted(True)
            self.dragOver = True
            self.update()
            log.debug("Drag Positive ENTER between topBand %r and botBand %r"%(topAltitude, bottomAltitude))
        # Accept a negative altitude band
        elif data['band'] < 0 and (topAltitude < 0 or bottomAltitude < 0):
            event.setAccepted(True)
            self.dragOver = True
            self.update()
            log.debug("Drag Negative ENTER between topBand %r and botBand %r"%(topAltitude, bottomAltitude))
        else:
            event.setAccepted(False)
            return
        self.setZValue(max([self.topBand.altitude if self.topBand else None,
                            self.bottomBand.altitude if self.bottomBand else None]))

    def dragLeaveEvent(self,event):
        self.dragOver = False
        self.update()

    def dropEvent(self,event):
        self.dragOver = False
        self.update()
        """ Reorder the band altitudes to put the dropped band in the new position"""
        # Not all bands are necessarily being shown due to the fact that depending
        # on the ordering of the blocks, edge connections could travel different
        # directions. When reordering bands, we need to take into account ALL
        # the bands (both shown and not shown).

        # Decode the drag metadata into a dict
        data = json.loads(str(event.mimeData().text()))
        # Get the altitude of the band that was dragged
        srcAlt = data['band']
        # Get the altitudes of the bands displayed above and below this spacer.
        topAltitude = self.topBand.altitude if self.topBand else None
        bottomAltitude = self.bottomBand.altitude if self.bottomBand else None
        log.debug("Moving Band %d between topBand %r and botBand %r"%(srcAlt, topAltitude, bottomAltitude))
        self._adapter.reorder_bands(srcAlt,bottomAltitude,topAltitude)

    def paint(self,painter,option,widget):
        if self.dragOver:
            pen = QPen()
            pen.setBrush(Qt.lightGray)
            pen.setStyle(Qt.DashLine)
            painter.setPen(pen)
        else:
            painter.setPen(Qt.NoPen)
        painter.drawRect(self.rect())

class BandItem(SpacerContainer.Item, QtBandItemAttributes):
    def __init__(self, parent, altitude, rank):
        self._layout_manager = typecheck(parent, LayoutManagerWidget, "parent")
        self._view = parent.view()
        self._adapter = parent.adapter()
        super(BandItem,self).__init__(parent,parent.bandStack)
        QtBandItemAttributes.__init__(self)

        # Band properties - these must be kept up to date with topology
        self.altitude = altitude
        self._rank = rank
        self.top_band = None
        self.bot_band = None
        self.left_most_snap = None
        self.right_most_snap = None

        # Set Qt properties
        self.setContentsMargins(5,5,5,5)
        self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding))
        self.set_width(15)
        self.setAcceptHoverEvents(True)
#         self.setZValue(rank)

    def release(self):
        self.top_band = None
        self.bot_band = None
        self.left_most_snap = None
        self.right_most_snap = None
        self.setParent(None)
        self.setVisible(False)
        super(BandItem, self)._release()

    def itemA(self):
        """ Set itemA to be the topBand """
        # This is computed and assigned by the adapter prior to linking
        return self.top_band

    def itemB(self):
        """ Set itemB to be the bottomBand """
        # This is computed and assigned by the adapter prior to linking
        return self.bot_band

    def isUsed(self):
        """ Deprecated """
        return True

    @property
    def rank(self):
        return self._rank
    @rank.setter
    def rank(self, value):
        self._rank = value
        self.setZValue(self._rank)

    def set_attributes(self, attrs):
        """ Applies a set of BandItemViewAttributes to this object. Transforms
        some values such as color into qt specific values. """
        typecheck(attrs, BandItemAttributes, "attrs")
        self.copy_attributes(attrs)
        self.set_width(self.width)
        self.update(self.rect())

    def set_width(self, width):
        """ Sets the 'width' of the band.
        This is actually setting the height, but is referred to as the width.
        """
        self.setPreferredHeight(width)
        self.setMinimumHeight(width)

    def isPositive(self):
        return True if self.altitude > 0 else False

    def link(self):
        sys.stdout.flush()
        # Assign the vertical anchors
        super(BandItem,self).link()
        # Assign the horizontal Anchors
        l = self.parent.layout()
        l.addAnchor(self, Qt.AnchorLeft, self.left_most_snap, Qt.AnchorLeft)
        l.addAnchor(self, Qt.AnchorRight, self.right_most_snap, Qt.AnchorRight)

    def mousePressEvent(self, event):
        """ This is necessary to capture the mouse clicking event to drag"""
        pass

    def mouseReleaseEvent(self, event):
        log.debug("Bringing band %d to front" % self.altitude)
        self._adapter.bring_band_to_front(self.altitude)

    def hoverEnterEvent(self, event):
        if self.tooltip_text:
            QToolTip.showText(event.screenPos(),self.tooltip_text)

    def hoverLeaveEvent(self, event):
        QToolTip.hideText()

    def mouseMoveEvent(self, event):
        if event.buttons() != Qt.LeftButton:
            super(BandItem,self).mouseMoveEvent(event)
        else:
            drag = QDrag(event.widget())
            mimeData = QMimeData()
            mimeData.setText(json.dumps({'band':self.altitude}))
            drag.setMimeData(mimeData)
            drag.start()

    def paint(self,painter,option,widget):
        brush = QBrush()
        brush.setStyle(Qt.SolidPattern)
        brush.setColor(self.bgcolor)
        painter.fillRect(self.rect(),brush)
        painter.setPen(self.border_color)
        painter.drawRect(self.rect())
        rect = self.geometry()
        painter.setPen(self.label_color)
        fm = painter.fontMetrics()
        elided = fm.elidedText(self.label, Qt.ElideRight, rect.width())
        twidth = fm.width(elided)
        painter.drawText((rect.width()-twidth)/2,rect.height()-2,elided)

class BlockContainer(SpacerContainer):
    def __init__(self, parent):
        super(BlockContainer,self).__init__(parent)
        self.spacerType = BlockSpacer
        self.parent = typecheck(parent,LayoutManagerWidget, "parent")
        self._view = parent.view()
        self._adapter = parent.adapter()
        self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred))
        self.setMinimumWidth(15)

    def paint(self, painter, option, widget):
        painter.setPen(Qt.NoPen)
        painter.drawRect(self.rect())

class BlockSpacer(SpacerContainer.Spacer):
    def __init__(self,parent):
        super(BlockSpacer,self).__init__(parent)
        self._view = parent.parent.view()
        self._adapter = parent.parent.adapter()
        self.dragOver = False
        self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Preferred))
        self.setPreferredWidth(50)
        self.setMinimumWidth(50)
        self.setAcceptDrops(True)

    @property
    def leftBlock(self):
        return self.itemA

    @property
    def rightBlock(self):
        return self.itemB

    def link(self):
        l = self.parent.parent.layout()
        # If you have a block to your left, connect
        if self.leftBlock:
            l.addAnchor(self, Qt.AnchorLeft, self.leftBlock, Qt.AnchorRight)
            l.addAnchor(self, Qt.AnchorTop, self.leftBlock, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorBottom, self.leftBlock, Qt.AnchorBottom)
        # Otherwise connect to left container edge
        else:
            l.addAnchor(self, Qt.AnchorLeft, self.parent, Qt.AnchorLeft)
            l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)

        # If you have a block to your right, connect
        if self.rightBlock:
            l.addAnchor(self, Qt.AnchorRight, self.rightBlock, Qt.AnchorLeft)
            l.addAnchor(self, Qt.AnchorTop, self.rightBlock, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorBottom, self.rightBlock, Qt.AnchorBottom)
        # Otherwise connect to the right container edge
        else:
            l.addAnchor(self, Qt.AnchorRight, self.parent, Qt.AnchorRight)
            l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)

    def dragEnterEvent(self,event):
        if not event.mimeData().hasText():
            event.setAccepted(False)
            return
        data = json.loads(str(event.mimeData().text()))
        if 'block' in data:
            if self.leftBlock and data['block'] == self.leftBlock.block_index:
                event.setAccepted(False)
                return
            if self.rightBlock and data['block'] == self.rightBlock.block_index:
                event.setAccepted(False)
                return
            event.setAccepted(True)
            self.dragOver = True
            log.debug("Drag ENTER")
            self.update()
        else:
            event.setAccepted(False)

    def dragLeaveEvent(self, event):
        self.dragOver = False
        self.update()

    def dropEvent(self, event):
        """ Dropping a 'block' on a BlockSpacer triggers a reordering event """
        self.dragOver = False
        self.update()
        # Dragged Index
        data = json.loads(str(event.mimeData().text()))
        if not 'block' in data:
            raise Exception("Wrong drag data type!")
        srcIdx = data['block']
        # Left Index
        lowerIdx = self.leftBlock.block_index if self.leftBlock else None
        upperIdx = self.rightBlock.block_index if self.rightBlock else None
        self._adapter.reorder_blocks(srcIdx, lowerIdx, upperIdx)

    def paint(self, painter, option, widget):
        if self.dragOver:
            pen = QPen()
            pen.setBrush(Qt.lightGray)
            pen.setStyle(Qt.DashLine)
            painter.setPen(pen)
        else:
            painter.setPen(Qt.NoPen)
        painter.drawRect(self.rect())

class BlockItem(SpacerContainer.Item, QtBlockItemAttributes):
    """ This is a QGraphicsWidget for a Diarc Block. """
    def __init__(self, parent, block_index):
        self._layout_manager = typecheck(parent, LayoutManagerWidget, "parent")
        self._view = parent.view()
        self._adapter = parent.adapter()
        super(BlockItem, self).__init__(parent, parent.block_container)
        QtBlockItemAttributes.__init__(self)

        # Qt Settings
        self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding))
        self.setPreferredHeight(5)
        self.setMinimumHeight(5)
        self.setContentsMargins(5,5,5,5)

        # Properties - these values must be kept up-to-date whenever the model changes
        self.block_index = block_index
        self.left_block = None
        self.right_block = None

        # We want to have a little space above and below the Emitter/Collector,
        # Set up top and bottom margin to give that space.
        self._topMargin = BlockItem.HorizontalSpacer(self)
        self._botMargin = BlockItem.HorizontalSpacer(self)
        self._middleSpacer = BlockItem.MiddleSpacer(self)

        # Set up Emitter and Collector Containers. They will sit "inside" the
        # block margins
        self.myEmitter = MyEmitter(self)
        self.myCollector = MyCollector(self)

    def set_attributes(self, attrs):
        typecheck(attrs, BlockItemAttributes, "attrs")
        self.copy_attributes(attrs)
        self._middleSpacer.set_width(self.spacerwidth)
        self.update(self.rect())

    def release(self):
        super(BlockItem, self)._release()
        self.left_block = None
        self.right_block = None
        self._topMargin.release()
        self._botMargin.release()
        self._middleSpacer.release()
        self._topMargin = None
        self._botMargin = None
        self._middleSpacer = None
        self.myEmitter.release()
        self.myCollector.release()
        self.myEmitter = None
        self.myCollector = None
        self._layout_manager = None
        self._view = None
        self._adapter = None

    def itemA(self):
        """ We use itemA for the BlockItem to the left. """
        # Get the index to our left, and return the BlockItem with that value
        return self.left_block

    def itemB(self):
        """ We use itemB for the BlockItem to the right. """
        # Get the index to our right, and return the BlockItem with that value
        return self.right_block

    def isUsed(self):
        return True

    def link(self):
        """ Link to other objects around you. In addition to linking to other
        blocks, we need to link to our top and bottom margins, and the emitter
        and collector containers
        """
        # Link with other BlockItems
        super(BlockItem, self).link()

        l = self.parent.layout()
        # Link with top and bottom margins
        l.addAnchor(self,Qt.AnchorTop, self._topMargin, Qt.AnchorTop)
        l.addAnchor(self,Qt.AnchorLeft, self._topMargin, Qt.AnchorLeft)
        l.addAnchor(self,Qt.AnchorRight, self._topMargin, Qt.AnchorRight)
        l.addAnchor(self,Qt.AnchorBottom, self._botMargin, Qt.AnchorBottom)
        l.addAnchor(self,Qt.AnchorLeft, self._botMargin, Qt.AnchorLeft)
        l.addAnchor(self,Qt.AnchorRight, self._botMargin, Qt.AnchorRight)

        # Link with emitter and collector containers
        l.addAnchor(self._topMargin, Qt.AnchorBottom, self.myEmitter, Qt.AnchorTop)
        l.addAnchor(self._botMargin, Qt.AnchorTop, self.myEmitter, Qt.AnchorBottom)
        l.addAnchor(self._topMargin, Qt.AnchorBottom, self.myCollector, Qt.AnchorTop)
        l.addAnchor(self._botMargin, Qt.AnchorTop, self.myCollector, Qt.AnchorBottom)

        l.addAnchor(self._middleSpacer, Qt.AnchorTop, self.myEmitter, Qt.AnchorTop)
        l.addAnchor(self._middleSpacer, Qt.AnchorTop, self.myCollector, Qt.AnchorTop)
        l.addAnchor(self._middleSpacer, Qt.AnchorBottom, self.myEmitter, Qt.AnchorBottom)
        l.addAnchor(self._middleSpacer, Qt.AnchorBottom, self.myCollector, Qt.AnchorBottom)

        l.addAnchor(self, Qt.AnchorLeft, self.myCollector, Qt.AnchorLeft)
        l.addAnchor(self, Qt.AnchorRight, self.myEmitter, Qt.AnchorRight)
        l.addAnchor(self.myCollector, Qt.AnchorRight, self._middleSpacer, Qt.AnchorLeft)
        l.addAnchor(self._middleSpacer, Qt.AnchorRight, self.myEmitter, Qt.AnchorLeft)

    def mousePressEvent(self, event):
        pass

    def mouseMoveEvent(self, event):
        """ Creates a drag event with the block information """
        if event.buttons() != Qt.LeftButton:
            super(BlockItem, self).mouseMoveEvent(event)
        else:
            drag = QDrag(event.widget())
            mimeData = QMimeData()
            mimeData.setText(json.dumps({'block': self.block_index}))
            drag.setMimeData(mimeData)
            drag.start()

    def paint(self,painter,option,widget):
        border_pen = QPen()
        border_pen.setBrush(self.border_color)
        border_pen.setStyle(Qt.SolidLine)
        border_pen.setWidth(self.border_width)
        painter.setPen(border_pen)
        painter.drawRect(self.rect())

    class MiddleSpacer(QGraphicsWidget):
        def __init__(self,parent):
            super(BlockItem.MiddleSpacer,self).__init__(parent=parent)
            # NOTE: I originally tried to set this to Preferred, MinimumExpanding
            # but ran into trouble when the layout could not compute itself when
            # it set that mode. For some reason, it was very unhappy about giving
            # it height policy information.
            self.blockItem = parent
            self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred))
            # The width of the block
            self.set_width(20)
            self.setAcceptHoverEvents(True)

        def set_width(self, width):
            self.setPreferredWidth(width)
            self.setMinimumWidth(width)

        def release(self):
            self.setParent(None)
            self.blockItem = None

        def hoverEnterEvent(self, event):
            if self.blockItem.tooltip_text:
                QToolTip.showText(event.screenPos(),self.blockItem.tooltip_text)

        def hoverLeaveEvent(self, event):
            QToolTip.hideText()

#         def event(self, event):
#             if event.type() == QEvent.ToolTip:
#             QToolTip.showText(event.screenPos(),self.label+" ToolTip!")
#         else:
#             QToolTip.hideText()
#             event.ignore()
#         return super(BlockItem, self).event(event)

        def paint(self,painter,option,widget):
            painter.setPen(Qt.NoPen)
            painter.drawRect(self.rect())
            painter.setPen(self.blockItem.label_color)
            painter.rotate(-90)
            rect = self.rect()
            fm = painter.fontMetrics()
            elided = fm.elidedText(self.blockItem.label, Qt.ElideRight, rect.height()-2)
            twidth = fm.width(elided)
            painter.drawText(-twidth-(rect.height()-twidth)/2,rect.width()-2,elided)

    class HorizontalSpacer(QGraphicsWidget):
        def __init__(self,parent):
            super(BlockItem.HorizontalSpacer,self).__init__(parent=parent)
            self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Preferred))
            self.setPreferredHeight(0)
            self.setMinimumHeight(0)
            self.setMaximumHeight(0)
            self.setMinimumWidth(5)

        def release(self):
            self.setParent(None)

class SnapContainer(SpacerContainer):
    def __init__(self,parent):
        super(SnapContainer, self).__init__(parent.parent)
        self.parentBlock = typecheck(parent, BlockItem, "parent")

        self.spacerType = SnapSpacer
        self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred))
        self.setMinimumWidth(1)
        self.setPreferredWidth(1)

    def release(self):
        super(SnapContainer, self)._release()
        self.parentBlock = None

    def strType(self):
        """ prints the container type as a string """
        return "emitter" if isinstance(self,MyEmitter) else "collector" if isinstance(self,MyCollector) else "unknown"

    def paint(self,painter,option,widget):
        painter.setPen(Qt.green)
        painter.drawRect(self.rect())

class MyEmitter(SnapContainer):
    def paint(self, painter, option, widget):
        if self.parentBlock.draw_debug:
            painter.setPen(Qt.green)
            painter.drawRect(self.rect())

class MyCollector(SnapContainer):
    def paint(self, painter, option, widget):
        if self.parentBlock.draw_debug:
            painter.setPen(Qt.blue)
            painter.drawRect(self.rect())

class SnapSpacer(SpacerContainer.Spacer):
    def __init__(self,parent):
        super(SnapSpacer,self).__init__(parent)
        self._layout_manager = parent.parent
        self._view = parent.parent.view()
        self._adapter = parent.parent.adapter()

        self.dragOver = False

        # Qt Properties
        self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Preferred))
        self.collapseWidth()
        self.setAcceptDrops(True)

    @property
    def leftSnap(self):
        return self.itemA

    @property
    def rightSnap(self):
        return self.itemB

    def link(self):
        l = self.parent.parent.layout()
        # If you have a snap to your left, connect
        if self.leftSnap:
            l.addAnchor(self, Qt.AnchorLeft, self.leftSnap, Qt.AnchorRight)
            l.addAnchor(self, Qt.AnchorTop, self.leftSnap, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorBottom, self.leftSnap, Qt.AnchorBottom)
        # Otherwise connect to left container edge
        else:
            l.addAnchor(self, Qt.AnchorLeft, self.parent, Qt.AnchorLeft)
            l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)
        # if you have a snap to your right, connect
        if self.rightSnap:
            l.addAnchor(self, Qt.AnchorRight, self.rightSnap, Qt.AnchorLeft)
            l.addAnchor(self, Qt.AnchorTop, self.rightSnap, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorBottom, self.rightSnap, Qt.AnchorBottom)
        # Otherwise connect to the right container edge
        else:
            l.addAnchor(self, Qt.AnchorRight, self.parent, Qt.AnchorRight)
            l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)

    def dragEnterEvent(self, event):
        """ Decides whether or not the information being dragged can be placed here"""
        if not event.mimeData().hasText():
            event.setAccepted(False)
            return
        data = json.loads(str(event.mimeData().text()))
        if not set(['block', 'container', 'snap']).issubset(set(data.keys())):
            event.setAccepted(False)
            return
        if not data['block'] == self.parent.parentBlock.block_index:
            event.setAccepted(False)
            return
        if not self.parent.strType() == data['container']:
            event.setAccepted(False)
            return
        if self.leftSnap and data['snap'] == self.leftSnap.snap_order:
            event.setAccepted(False)
            return
        if self.rightSnap and data['snap'] == self.rightSnap.snap_order:
            event.setAccepted(False)
            return
        event.setAccepted(True)
        self.expandWidth()
        self.dragOver = True
        self.update()

    def dragLeaveEvent(self, event):
        self.dragOver = False
        self.collapseWidth()
        self.update()

    def dropEvent(self,event):
        """ Relocates a MySnap to this position """
        self.collapseWidth()
        self.dragOver = False
        data = json.loads(str(event.mimeData().text()))
        assert(data['block'] == self.parent.parentBlock.block_index)
        assert(data['container'] == self.parent.strType())

        srcIdx = data['snap']
        lowerIdx = self.leftSnap.snap_order if self.leftSnap else None
        upperIdx = self.rightSnap.snap_order if self.rightSnap else None
        self._adapter.reorder_snaps(data['block'], data['container'], srcIdx, lowerIdx, upperIdx)

    def paint(self, painter, option, widget):
        if self.dragOver:
            brush = QBrush()
            brush.setStyle(Qt.Dense4Pattern)
            brush.setColor(Qt.yellow)
            painter.fillRect(self.rect(),brush)
            pen = QPen()
            pen.setBrush(Qt.darkGray)
            pen.setStyle(Qt.DotLine)
            pen.setWidth(1)
            painter.setPen(pen)
            painter.drawRect(self.rect())
            rect = self.geometry()
        else:
            painter.setPen(Qt.NoPen)
#             painter.setPen(Qt.magenta)
            painter.drawRect(self.rect())

    def collapseWidth(self):
        """ Make the width very small """
        self.setMinimumWidth(0.1)
        self.setMaximumWidth(0.1)
        self.setPreferredWidth(0.1)

    def expandWidth(self):
        """ Widen the spacer to afford seperation """
        self.setMinimumWidth(10)
        self.setMaximumWidth(10)
        self.setPreferredWidth(10)

class SnapItem(SpacerContainer.Item, QtSnapItemAttributes):
    def __init__(self, parent, snapkey):
        QtSnapItemAttributes.__init__(self)
        block_index, container_name, snap_order = parse_snapkey(snapkey)
        self._snapkey = snapkey
        self._layout_manager = typecheck(parent, LayoutManagerWidget, "parent")
        self._view = parent.view()
        self._adapter = parent.adapter()

        assert(container_name in ["emitter","collector"])
        self.block_index = block_index
        self.snap_order = snap_order
        self.block_item = self._layout_manager.get_block_item(block_index)
        self.container = self.block_item.myEmitter if container_name == "emitter" else self.block_item.myCollector
        # SnapItems to the left and to the right - populated by the adapter
        self.left_snap = None
        self.right_snap = None
        # Positive and Negative BandItems this snap connects to - only exists if
        # the band is being used - populated by the adapter
        self.posBandItem = None
        self.negBandItem = None
        super(SnapItem,self).__init__(parent,self.container)

        # Qt Properties
        self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred))
        self.set_width(20)
        # These values dictate the block Container Height
        self.setPreferredHeight(150)
        self.setMaximumHeight(150)

        #Create two SnapBandLinks - one for each band
        _is_source = True if container_name == "emitter" else False
        self.upLink = SnapBandLink(None, is_uplink=True, is_source=_is_source)
        self.downLink = SnapBandLink(None,is_source=_is_source)

    def release(self):
        self.left_snap = None
        self.right_snap = None
        self.upLink.setParent(None)
        self.downLink.setParent(None)
        self.upLink = None
        self.downLink = None
        self.setVisible(False)
        super(SnapItem, self)._release()

    def itemA(self):
        """ We use itemA for the SnapItem to the left """
        return self.left_snap

    def itemB(self):
        """ We use itemB for the SnapItem to the right """
        # When we don't display unused snaps, we are still reporting unused snaps to
        # our left and right here - only they don't visually exists which causes problems
        return self.right_snap

    def isUsed(self):
        """ Deprecated """
        return True

    def set_attributes(self, attrs):
        typecheck(attrs, SnapItemAttributes, "attrs")
        self.copy_attributes(attrs)
        self.set_width(attrs.width)
        self.update(self.rect())

    def set_width(self, width):
        self.width = width
        self.setPreferredWidth(width)

    def link(self):
        super(SnapItem, self).link()
        l = self.parent.layout()
        l.addAnchor(self, Qt.AnchorTop, self.container, Qt.AnchorTop)
        l.addAnchor(self, Qt.AnchorBottom, self.container, Qt.AnchorBottom)

        #Connect bandlinks
        if self.posBandItem:
            self.upLink.setVisible(True)
            self.upLink.setZValue(self.posBandItem.rank+0.5)
            l.addAnchor(self, Qt.AnchorTop, self.upLink, Qt.AnchorBottom)
            l.addAnchor(self.posBandItem, Qt.AnchorBottom, self.upLink, Qt.AnchorTop)
            l.addAnchor(self, Qt.AnchorLeft, self.upLink, Qt.AnchorLeft)
            l.addAnchor(self, Qt.AnchorRight, self.upLink, Qt.AnchorRight)
            self.upLink.bgcolor = self.posBandItem.bgcolor
            self.upLink.border_color = self.posBandItem.border_color
            self.upLink.label_color = self.posBandItem.label_color
        else:
            self.upLink.setVisible(False)
            self.upLink.setParent(None)

        if self.negBandItem:
            self.downLink.setVisible(True)
            self.downLink.setZValue(self.negBandItem.rank+0.5)
            l.addAnchor(self, Qt.AnchorBottom, self.downLink, Qt.AnchorTop)
            l.addAnchor(self.negBandItem, Qt.AnchorTop, self.downLink, Qt.AnchorBottom)
            l.addAnchor(self, Qt.AnchorLeft, self.downLink, Qt.AnchorLeft)
            l.addAnchor(self, Qt.AnchorRight, self.downLink, Qt.AnchorRight)
            self.downLink.bgcolor = self.negBandItem.bgcolor
            self.downLink.border_color = self.negBandItem.border_color
            self.downLink.label_color = self.negBandItem.label_color
        else:
            self.downLink.setVisible(False)
            self.downLink.setParent(None)

    def mousePressEvent(self, event):
        """ Captures the mouse press event for dragging """
        pass

    def mouseReleaseEvent(self, event):
        if self.posBandItem:
            self._adapter.bring_band_to_front(self.posBandItem.altitude)
        if self.negBandItem:
            self._adapter.bring_band_to_front(self.negBandItem.altitude)

    def mouseMoveEvent(self, event):
        if event.buttons() != Qt.LeftButton:
            super(SnapItem,self).mouseMoveEvent(event)
        else:
            drag = QDrag(event.widget())
            mimeData = QMimeData()
            mimeData.setText(json.dumps({'block': self.block_index,'container': self.container.strType(),'snap':self.snap_order}))
            drag.setMimeData(mimeData)
            drag.start()

    def paint(self, painter, option, widget):
        # Paint background
        brush = QBrush()
        brush.setStyle(Qt.SolidPattern)
        brush.setColor(self.bgcolor)
        painter.fillRect(self.rect(),brush)
        # Paint border
        border_pen = QPen()
        border_pen.setBrush(self.border_color)
        border_pen.setStyle(Qt.SolidLine)
        border_pen.setWidth(self.border_width)
        painter.setPen(border_pen)
        painter.drawRect(self.rect())
        rect = self.geometry()
        painter.setPen(self.label_color)
        if self.draw_debug:
            if self.posBandItem:
                painter.drawText(6,12,str(self.posBandItem.altitude))
            if self.negBandItem:
                painter.drawText(3,rect.height()-3,str(self.negBandItem.altitude))
#         painter.drawText(2,rect.height()/2+4,self.label)
        painter.rotate(-90)
        fm = painter.fontMetrics()
        elided = fm.elidedText(self.label, Qt.ElideRight, rect.height())
        twidth = fm.width(elided)
        painter.drawText(-twidth-(rect.height()-twidth)/2,rect.width()-2,elided)

class SnapBandLink(QGraphicsWidget, QtBandItemAttributes):
    def __init__(self,parent, is_uplink=False, is_source=False):
        super(SnapBandLink,self).__init__(parent=parent)
        QtBandItemAttributes.__init__(self)
        self.setVisible(False)
        self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.MinimumExpanding))
        self.setPreferredWidth(5)
        self.setMinimumWidth(5)
        self.setPreferredHeight(5)
        self.setMinimumHeight(5)

        self._is_uplink = is_uplink
        self._is_source = is_source

    def paint(self,painter,option,widget):
        brush = QBrush()
        brush.setStyle(Qt.SolidPattern)
        brush.setColor(self.bgcolor)
        painter.fillRect(self.rect(),brush)
        pen = QPen()
        pen.setBrush(self.border_color)
        pen.setStyle(Qt.DashLine)
        rect = self.rect()
        painter.setPen(pen)
        painter.drawRect(rect)
        # Create arrows
        arrow_scale = 0.5
        arrow_width = rect.width()*arrow_scale
        arrow_height = arrow_width * 0.8
        arrow_margin = (rect.width()-arrow_width)/2.0

        brush.setColor(self.label_color)
        painter.setPen(Qt.NoPen)
        painter.setBrush(brush)
        arrow = None
        # Determine which direction to draw arrow
        if (self._is_uplink and self._is_source) or (not self._is_uplink and not self._is_source):
            # Draw pointing up
            arrow = QPolygon([QPoint(0,arrow_height), QPoint(arrow_width,arrow_height), QPoint(arrow_width/2.0,0)])
        else:
            # Draw pointing down
            arrow = QPolygon([QPoint(0,0), QPoint(arrow_width,0), QPoint(arrow_width/2.0,arrow_height)])

        # Determine which side to draw arrow on
        if self._is_uplink:
            arrow.translate(rect.x()+arrow_margin,rect.y()+rect.height()-arrow_height-arrow_margin)
        else:
            arrow.translate(rect.x()+arrow_margin,rect.y()+arrow_margin)
        painter.drawPolygon(arrow)

class LayoutManagerWidget(QGraphicsWidget):
    """ Holds the actual qt anchoredlayout and top level SpacerContainers """
    def __init__(self, view):
        super(LayoutManagerWidget, self).__init__(parent=None)
        self._view = view
        self.resize(0,0)

        # Top Level Layout Containers
        self.block_container = BlockContainer(self)
        self.bandStack = BandStack(self)

        # Visual Object we are tracking
        self._block_items = TypedDict(int,BlockItem)  # index    #TypedList(BlockItem)
        self._band_items = TypedDict(int,BandItem)    # altitude    #TypedList(BandItem)
        self._snap_items = TypedDict(str,SnapItem)  # snapkey  #TypedList(SnapItem)

    def add_block_item(self, index):
        log.debug("... Adding BlockItem %d"%index)
        """ create a new BlockItem """
        if index in self._block_items:
            raise DuplicateItemExistsError("Block Item with index %d already exists"%(index))
        item = BlockItem(self, index)
        self._block_items[index] = item
        return item

    def has_block_item(self, index):
        return True if index in self._block_items else False

    def set_block_item_settings(self, index, left_index, right_index):
        item = self._block_items[index]
        item.left_block = self._block_items[left_index] if left_index is not None else None
        item.right_block = self._block_items[right_index] if right_index is not None else None

    def set_block_item_attributes(self, index, attributes):
        self._block_items[index].set_attributes(attributes)

    def remove_block_item(self, index):
        log.debug("... Removing BlockItem %d"%index)
        self._block_items[index].release()
        self._block_items.pop(index)

    def get_block_item(self, index):
        """ Returns a BlockItem with specified index """
        return self._block_items[index]

    def add_band_item(self, altitude, rank):
        """ Create a new drawable object to correspond to a Band. """
        log.debug("... Adding BandItem with altitude %d"%altitude)
        if altitude in self._band_items:
            raise DuplicateItemExistsError("BandItem with altitude %d already exists"%(altitude))
        item = BandItem(self, altitude, rank)
        self._band_items[altitude] = item
        return item

    def has_band_item(self, altitude):
        return True if altitude in self._band_items else False

    def remove_band_item(self, altitude):
        """ Remove the drawable object to correspond to a band """
        log.debug("... Removing BandItem altitude %d"%altitude)
        self._band_items[altitude].release()
        self._band_items.pop(altitude)

    def get_band_item(self, altitude):
        return self._band_items[altitude]

    def set_band_item_settings(self, altitude, rank,
                                top_band_alt, bot_band_alt,
                                leftmost_snapkey, rightmost_snapkey):
        item = self._band_items[altitude]
        item.rank = rank
        item.top_band = self._band_items[top_band_alt] if top_band_alt is not None else None
        item.bot_band = self._band_items[bot_band_alt] if bot_band_alt is not None else None
        item.left_most_snap = self._snap_items[str(leftmost_snapkey)]
        item.right_most_snap = self._snap_items[str(rightmost_snapkey)]

    def set_band_item_attributes(self, altitude, attrs):
        self._band_items[altitude].set_attributes(attrs)

    def add_snap_item(self, snapkey):
        # snapkey gets passed as a QString automatically since it goes across
        # a signal/slot interface
        snapkey = str(snapkey)
        log.debug("... Adding SnapItem %s"%snapkey)
        if snapkey in self._snap_items:
            raise DuplicateItemExistsError("SnapItem with snapkey %s already exists"%(snapkey))
        item = SnapItem(self, snapkey)
        self._snap_items[snapkey] = item
        return item

    def remove_snap_item(self, snapkey):
        # snapkey gets passed as a QString automatically since it goes across
        # a signal/slot interface
        snapkey = str(snapkey)
        log.debug("... Removing SnapItem %s"%snapkey)
        self._snap_items[snapkey].release()
        self._snap_items.pop(snapkey)

    def has_snap_item(self, snapkey):
        return True if snapkey in self._snap_items else False

    def get_snap_items(self, snapkey):
        # snapkey gets passed as a QString automatically since it goes across
        # a signal/slot interface
        snapkey = str(snapkey)
        return self._snap_item[snapkey]

    def set_snap_item_settings(self, snapkey, left_order, right_order, pos_band_alt, neg_band_alt):
        # snapkey gets passed as a QString automatically since it goes across
        # a signal/slot interface
        snapkey = str(snapkey)
        item = self._snap_items[snapkey]
        if left_order is not None:
            left_snapkey = gen_snapkey(item.block_index,item.container.strType(),left_order)
            item.left_snap = self._snap_items[left_snapkey]
        else:
            item.left_snap = None
        if right_order is not None:
            right_snapkey = gen_snapkey(item.block_index,item.container.strType(),right_order)
            item.right_snap = self._snap_items[right_snapkey]
        else:
            item.right_snap = None
        item.posBandItem = self._band_items[pos_band_alt] if pos_band_alt is not None else None
        item.negBandItem = self._band_items[neg_band_alt] if neg_band_alt is not None else None

    def set_snap_item_attributes(self, snapkey, attributes):
        # snapkey gets passed as a QString automatically since it goes across
        # a signal/slot interface
        snapkey = str(snapkey)
        self._snap_items[snapkey].set_attributes(attributes)

    def view(self):
        return self._view

    def adapter(self):
        return self._view.adapter

    def link(self):
        log.debug("*** Begining Linking ***")
        sys.stdout.flush()
        # Create a new anchored layout. Until I can figure out how to remove
        # objects from the layout, I need to make a new one each time
        l = QGraphicsAnchorLayout()
        l.setSpacing(0.0)
        self.setLayout(l)

        # Anchor BandStack to Layout, and BlockContainer to BandStack
        self.layout().addAnchor(self.block_container, Qt.AnchorTop, self.layout(), Qt.AnchorTop)
        self.layout().addAnchor(self.block_container, Qt.AnchorLeft, self.layout(), Qt.AnchorLeft)
        self.layout().addAnchor(self.bandStack, Qt.AnchorLeft, self.block_container, Qt.AnchorLeft)
        self.layout().addAnchor(self.bandStack, Qt.AnchorRight, self.block_container, Qt.AnchorRight)

        # Link block items
        for item in self._block_items.values():
            item.link()

        # Link band items
        for item in self._band_items.values():
            item.link()

        # Link Snap Items
        for item in self._snap_items.values():
            item.link()

        log.debug("*** Finished Linking ***\n")
        sys.stdout.flush()

#     def mousePressEvent(self, event):
#         print "updating model"
#         self.adapter().update_model()
#
#     def paint(self, painter, option, widget):
#         painter.setPen(Qt.blue)
#         painter.drawRect(self.rect())

class QtView(QGraphicsView, View):
    """ This is a Qt based stand-alone widget that provides a visual rendering
    of a Topology. It provides a window into a self contained GraphicsScene in
    which we draw the topology.
    It also implements the View interface as a passthrough to the LayoutManager.
    """
    # Qt Signals. The following signals correspond to diarc.View() API calls that
    # are called from outside the main qt thread. Rather then call the implementations
    # defined in layout_manager directly, we call them from these signals so that
    # the call happens from the correct thread.
    __update_view_signal = Signal()

    __add_block_item_signal = Signal(int)
    __remove_block_item_signal = Signal(int)
    __set_block_item_settings_signal = Signal(int, object, object)
    __set_block_item_attributes_signal = Signal(int, BlockItemAttributes)

    __add_band_item_signal = Signal(int, int)
    __remove_band_item_signal = Signal(int)
    __set_band_item_settings_signal = Signal(int, int, object, object, str, str)
    __set_band_item_attributes_signal = Signal(int, BandItemAttributes)

    __add_snap_item_signal = Signal(str)
    __remove_snap_item_signal = Signal(str)
    __set_snap_item_settings_signal = Signal(str, object, object, object, object)
    __set_snap_item_attributes_signal = Signal(str, SnapItemAttributes)

    def __init__(self):
        super(QtView, self).__init__(None)
        View.__init__(self)

        # Qt properties - Enable click-n-drag paning and initialize Scene
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        self.setScene(QGraphicsScene(self))

        # Enable for debuging
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)

        # Add the LayoutManagerWidget to the scene
        self.layout_manager = LayoutManagerWidget(self)
        self.scene().addItem(self.layout_manager)

        # Hook up the signals and slots
        self.__update_view_signal.connect(self.layout_manager.link)
        self.__add_block_item_signal.connect(self.layout_manager.add_block_item)
        self.__remove_block_item_signal.connect(self.layout_manager.remove_block_item)
        self.__set_block_item_settings_signal.connect(self.layout_manager.set_block_item_settings)
        self.__set_block_item_attributes_signal.connect(self.layout_manager.set_block_item_attributes)
        self.__add_band_item_signal.connect(self.layout_manager.add_band_item)
        self.__remove_band_item_signal.connect(self.layout_manager.remove_band_item)
        self.__set_band_item_settings_signal.connect(self.layout_manager.set_band_item_settings)
        self.__set_band_item_attributes_signal.connect(self.layout_manager.set_band_item_attributes)
        self.__add_snap_item_signal.connect(self.layout_manager.add_snap_item)
        self.__remove_snap_item_signal.connect(self.layout_manager.remove_snap_item)
        self.__set_snap_item_settings_signal.connect(self.layout_manager.set_snap_item_settings)
        self.__set_snap_item_attributes_signal.connect(self.layout_manager.set_snap_item_attributes)
        self.resize(1024,768)
        QColor.setAllowX11ColorNames(True)
        if not QColor.allowX11ColorNames():
            rospy.logwarn("Coloring will not work properly")
        self.show()

    def update_view(self):
        self.__update_view_signal.emit()

    def add_block_item(self, index):
        """ Allows the adapter to create a new BlockItem """
        self.__add_block_item_signal.emit(index)

    def has_block_item(self, index):
        return self.layout_manager.has_block_item(index)

    def remove_block_item(self, index):
        self.__remove_block_item_signal.emit(index)

    def set_block_item_settings(self, index, left_index, right_index):
        return self.__set_block_item_settings_signal.emit(index, left_index, right_index)

    def set_block_item_attributes(self, index, attributes):
        self.__set_block_item_attributes_signal.emit(index, attributes)

    def add_band_item(self, altitude, rank):
        """ Create a new drawable object to correspond to a Band. """
        self.__add_band_item_signal.emit(altitude, rank)

    def has_band_item(self, altitude):
        return self.layout_manager.has_band_item(altitude)

    def remove_band_item(self, altitude):
        """ Remove the drawable object to correspond to a band """
        self.__remove_band_item_signal.emit(altitude)

    def set_band_item_settings(self, altitude, rank, top_band_alt, bot_band_alt,
                                leftmost_snapkey, rightmost_snapkey):
        self.__set_band_item_settings_signal.emit(altitude, rank, top_band_alt, bot_band_alt, leftmost_snapkey, rightmost_snapkey)

    def set_band_item_attributes(self, altitude, attributes):
        self.__set_band_item_attributes_signal.emit(altitude, attributes)

    def add_snap_item(self, snapkey):
        self.__add_snap_item_signal.emit(snapkey)

    def has_snap_item(self, snapkey):
        return self.layout_manager.has_snap_item(snapkey)

    def remove_snap_item(self, snapkey):
        self.__remove_snap_item_signal.emit(snapkey)

    def set_snap_item_settings(self, snapkey, left_order, right_order, pos_band_alt, neg_band_alt):
        self.__set_snap_item_settings_signal.emit(snapkey, left_order, right_order, pos_band_alt, neg_band_alt)

    def set_snap_item_attributes(self, snapkey, attributes):
        self.__set_snap_item_attributes_signal.emit(snapkey, attributes)

    def wheelEvent(self,event):
        """ Implements scrollwheel zooming """
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        scaleFactor = 1.15
        if event.delta() > 0:
            self.scale(scaleFactor, scaleFactor)
        else:
            self.scale(1.0/scaleFactor, 1.0/scaleFactor)

class DuplicateItemExistsError(Exception):
    """ An Item with the specified parameters already exists """
    pass

redpajama_set_name: RedPajamaGithub


text:
The Road to Hampden Blog – Third Round
Sunday 4 December 2016
At the weekend the William Hill Scottish Cup Third Round continued with Beith and Greenock Morton playing their rearranged match to decide who would face Falkirk in the next round.
Student Ronnie Charters was there to take in the match and sample the magic of the William Hill Scottish Cup.
They say you see some crazy sights in cup competitions, none more so than in the Scottish Cup.
But if you were to tell any of my university lecturers that I turned up early for something, they would say that is one of the craziest sights you are likely to see.
But alas that tendency is dispelled rather quickly if football is on the agenda.
That being said however my trip to the small Ayrshire town of Beith takes the biscuit in terms of punctuality.
Thinking it was a 12:30 kick-off I arrived in Beith at noon, looking to take in some of the sights and sounds.
After a walk around the streets and a top quality bag of chips from Fryer Tuck's Chip Shop I headed down to Bellsdale Park, where the stage was set for a blockbuster afternoon in the Scottish Cup.
In the walk down to the stadium I began to sense just how big an occasion this game was for the town.
After walking by a convenience store that had a sign on the door saying 'Closed for the Beith Game', it dawned on me that this little town in the corner of Ayrshire was gripped with cup fever.
As I made my final ascent toward the stadium, the home supporters in their black and white attire made their presence felt in and around Bellsdale Park.
If I never hear 'C'mon the Mighty' again I won't complain, but the home support certainly did their job in creating a cauldron of noise as the players emerged from the tunnel.
Submerged amongst the Beith Juniors faithful for the game, I fell in love with the sights and sounds a junior ground can produce.
I must also applaud the 1000 or so travelling Morton fans who made the 40 mile round trip and were certainly not letting the bitter chill in the air dampen their spirits.
In the early stages to everyone's amazement it was Beith who came out the traps absolutely flying.
John Millar's side deployed a game of high octane pressing, pace and power that wouldn't have looked out of place in the Premier League never mind a junior side, and if it wasn't for the reflexes of the Morton keeper, we may well have had a fairytale story on our hands.
Chance after chance fell to 'The Mighty' in the opening minutes enough to make Morton manager Jim Duffy a little edgy.
But it wasn't until the 11th minute that the Ton showed their first real touch of class, all thanks to the left foot of Ross Forbes.
In the blink of an eye, Forbes steered the ball around the wall and low into the Beith net, setting the tone for what was to follow.
At the break Beith were three down and as the whistle sounded an elderly gentlemen standing next to me rightly said, "Oh dear, is it only half-time, this could be nine or ten!"
I must admit you'll see no better sight in any cup competition than when the half-time whistle is blown in a game and straight away thirty small kids run onto the pitch to try and score into the Beith goal.
The magic of the cup personified, the smallest supporters wanting to score for their local team and the Scottish Cup.
Anyway, nostalgia over and back to the game.
Sadly for the Beith fans the second half was practically a mirror of the first. With John Millar's words still ringing in the players ears they showed a glimmer of resilience in the first five minutes of the second half (by resilience I mean not to concede a goal).
I spoke to a friend who is a Morton fan before the game and he said one thing, 'Beware of Tam O'Ware'.
That statement jolted back to me like a shockwave as O'Ware added number four to the Morton tally with a stunning 25-yard strike to the bottom left corner.
Celtic loanee Jamie Linsday added number five just before the eightieth minute when O'Ware bulleted a header to make it a resounding 6-0 win for the Ton.
Being a journalism student who is supposed to be covering the game as a neutral, I was urging the Beith players forward in the dying minutes to give the deserving home fans something to cheer about.
But alas it wasn't to be.
To sign off I leave you with the quote of the day from one of the ladies in the canteen who, when I was leaving the ground to make the trip back to Glasgow, obviously looking cold and tired, shouted to me:
"It's alright son, you've got the X Factor to look forward to tonight!"
I will say this; Beith Juniors have certainly made one new supporter.
Stage set for Scottish Cup Third Round
Scottish Cup entertainment beats the freeze
Scottish Cup Second Round to kick-off this weekend


text:
<?php

use auth\Context;
use connection\AuthModel;
use spitfire\Model;
use spitfire\storage\database\Schema;

/**
 *
 * @todo Add ownership to the apps. So a certain user can administrate his own apps
 */
class AuthAppModel extends Model
{

	public function definitions(Schema $schema) {
		$schema->appID  = new StringField(20);
		$schema->appSecret = new StringField(50);

		$schema->name   = new StringField(20);
		$schema->url    = new StringField(100);
		$schema->icon   = new FileField();

		/*
		 * System applications do not need to request permissions to access data,
		 * nor will the user be able to block them. In return, sys apps are only
		 * able to create tokens for administrative users.
		 */
		$schema->system = new BooleanField();
		$schema->system->setNullable(false);

		/*
		 * Indicates whether this application should be placed in the app drawer.
		 * This allows applications (including PHPAS) to quickly render navigation
		 * to provide users with the option to jump between apps.
		 */
		$schema->drawer = new BooleanField();
		$schema->drawer->setNullable(false);

		$schema->appID->setUnique(true);
	}

	public function canAccess($app, $user, $context) {

		$db = $this->getTable()->getDb();
		$q  = $db->table('connection\auth')->getAll();

		$q->addRestriction('source', $this);
		$q->addRestriction('target', $app);
		$q->addRestriction('context', $context);

		if ($user) {
			$q->addRestriction('user', $user);
		}
		else {
			$q->addRestriction('user', null, 'IS');
		}

		$q->group()->addRestriction('expires', null, 'IS')->addRestriction('expires', time(), '>');
		$result = $q->all();

		$_r = $result->reduce(function (AuthModel$c, AuthModel$e) {
			if ($e->user && $e->final) { return $e; }
			if ($c->user && $c->final) { return $c; }
			if ($e->user && $e->state == AuthModel::STATE_DENIED) { return $e; }
			if ($c->user && $c->state == AuthModel::STATE_DENIED) { return $c; }
			if ($e->final) { return $e; }
			if ($c->final) { return $c; }
			if ($e->user ) { return $e; }
			if ($c->user ) { return $c; }
			return $e;
		}, $result->rewind());

		return $_r? $_r->state : AuthModel::STATE_PENDING;
	}

	public function getContext($context) {
		if (!is_string($context)) {
			throw new InvalidArgumentException('Context must be string', 1806130942);
		}

		$db = $this->getTable()->getDb();
		$q  = $db->table('connection\context')->getAll();

		$q->addRestriction('app', $this);
		$q->addRestriction('ctx', $context);
		$q->group()->addRestriction('expires', time(), '>')->addRestriction('expires', null, 'IS');

		$r = $q->fetch();

		return $r? new Context(true, $r->ctx, $r->app->appID, $r->title, $r->descr, $r->expires) :
			new Context(false, $context, $this->appID, null, null, null);
	}

	public function __toString() {
		return sprintf('App (%s)', $this->name);
	}

}


Posting this week's episode a bit early, because it seems if we are going to post an episode about Black Friday, it would be fun to do it on Black Friday! In addition to a great Post of the Week about the history of Black Friday and best practices in leveraging the annual Celebration of Consumerism, this week's episode includes a Conversational Chaos with Aldo and his friend Riley about evil corporations and Christmas Lists! The show continues on with part 2 of our ongoing multi-part Red Dead Redemption 2 review.


In an attempt to provide increased value to our visitors, Nicotine Labs may link to sites operated by third parties. However, even if the third party is affiliated with Nicotine Labs, Nicotine Labs has no control over these linked sites, all of which have separate privacy and data collection practices, independent of Nicotine Labs. These linked sites are only for your convenience and therefore you access them at your own risk. Nonetheless, Nicotine Labs seeks to protect the integrity of its web site and the links placed upon it and therefore requests any feedback on not only its own site, but for sites it links to as well (including if a specific link does not work).


text:
Too poor to afford food, too rich to qualify for help
At age 69, Sandi Zahar takes home around $3,100 a month from Social Security and her part-time job, but still relies on a food bank.
She has diabetes and is a cancer survivor, and estimates that about a third of her income goes to her health care costs. Her income is too high to qualify for food stamps or Medicaid. And she needs to keep working to make ends meet.
"I don't know how long I am going to be able to work," said Zahar, who lives in Texas. "Physically, I probably shouldn't be working … it's taking a toll on my body."
She's had to make some tough decisions on how to cut back.
"I went on an insulin pump because Medicare pays for it. I don't like it, it's not as good for me, but it's cheaper," she said.
Millions of Americans like her make too much money to qualify for federal assistance, but struggle to afford to put food on the table.
More than 41 million people are "food insecure," meaning they don't have consistent access to adequate food, according to Feeding America. One in four people who are food insecure aren't likely to be eligible for most federal nutrition programs, a recent report from the hunger-relief organization found.
That means they either go hungry, skip meals, or rely on food banks to fill in the gaps.
Zahar gets a box of food from the food bank once a month.
She's careful with how she spends money on food, buying in bulk when she can and cooking longer-lasting meals.
Though the economy has greatly improved since the Great Recession, life is getting more expensive: Consumer prices have been rising, and while wages have started to tick up, some workers are finding their paychecks are being stretched too thin.
The rate of food insecurity is currently higher than it was before the Great Recession.
"Even in what seems to be a robust economic recovery, food insecurity remains at a historically high level," Feeding America President Matt Knott.
Nearly every county in the country has families that can't afford to put an adequate amount of food on the table. Many earn too much to get government assistance. The problem tends to be more prevalent in the South and rural areas. Jefferson County, Mississippi, has the highest rate of food insecurity at 36%. Nearby Issaquena County has the highest number of children facing food insecurity at 40%.
In every state, children are more likely than the general population to live in a home at risk of hunger, the report found.
"The majority of people our pantries are serving aren't eligible [for government assistance]. We hear stories that they earn $1 or $2 over the limit," said Sarah Ormbrek, community relations director for Second Harvest, which is part of the Feeding America family.
Ormbrek herself once relied on food banks and government aid to get by and had to make some tough choices. "I skipped meals, I was trying to get the most out of the money. So fresh vegetables or any fresh foods were out of the question. It was the cheapest processed lunch meat I could find," she recalled.
"To this day, my son doesn't like pancakes. I would water down the batter to make it last longer."
Source: http://money.cnn.com/2018/05/30/news/economy/food-insecurity-food-banks/index.html?utm_term=link&utm_medium=social&utm_source=fbmoney&utm_content=2018-06-22T01:30:01
Robot Cities: Three Urban Prototypes for Future Living
We Already Grow Enough Food For 10 Billion People — and Still Can't End Hunger


text:
The Helmet Decals of the Third Reich - by Ken Niewiarowicz (with Anders Lehrmann) - Book
135 160 £135.00 - £160.00
Store > Military Books > The Helmet Decals of the Third Reich
Book by Ken Niewiarowicz (with Anders Lehrmann), a helmet collectors decal 'bible'.
The book has over 300 pages and covers not only the branches of the Reichswehr and Wehrmacht, but also Polizei and other organizations including the Waffen SS decals. The author Ken Niewiarowicz, together with his co-author Anders Lehrman, categorizes and analyses in depth for the first time in the history of helmet collecting the decals of the Third Reich.
The research starts with the Reichswehr in spring 1918 and ends with a detailed look at decals of the foreign legions of the Waffen-SS. The authors have compiled the most complete compendium on this topic, including the latest research about the so-called "Champagne Decal."
The book is in full color and has more than 1000 photos.
Country -- UK USA & Canada Europe Worldwide (outside USA , Canada & Europe)


Tuesday was again an official rest day. That means an hour long walk for me. My knee still hurt from falling on Saturday so it wasn't the most pleasant experience. Plus we got a seriously strong rainshower during the last 15 minutes of our walk. I had to squeeze my sweater to get all the water out, my sneakers needed a whole day to dry.
Wednesday was Zumba day. We did about half an hour of dancing and then added some muscle exercises for legs, back and abs. And ofcourse I did my regular doggy-walking for half an hour.
On Thursday the crappy weather continued but it cleared up by evening. In the afternoon I did a regular walk, in the evening decided to go for my first run after Narva Energy Run. I thought I was fast and I was: 8 km/h. That's fast for me although it might be slow for a lot of people.
Friday surprised me with gorgeous weather, it was nice, warm and sunny. But still autumnal. Did a walk with my dog and in the evening jumped on my bicycle. A regular hour of cycling.
Saturday I had to go shopping because I needed long running tights (yay!) and school supplies (not so yay). Found some Nike tights for only 33€ and an Adidas jacket for 23€, so I couldn't leave that behind. I cycled to the city and back, about 35 minutes in total. In the evening did a 30 minute walk with my doggy.
Sunday was running day. Somehow my legs were total jello and I felt like a snail. But I did not stop or walk so I can be proud. Plus I ate dinner only an hour before workout so I felt the food in my stomach. You should have at least 2 hours between eating and working out. Not a good running day at all.
It was a good week: 9 hours of moving, no muscle or nerve pain (only my knee and elbow hurt from falling last Saturday) and new workout clothes.


text:
Q: Tagging docker image with tag from git repository I am using Gitlab for repository and ci/cd.
Currently trying to set up pipeline that creates a docker image from a build stage.
All examples I have seen have a simple naming of image where e.g. the branch is used(master)
My question is if I want to tag the image based on the current tag in the repository how do I do this?
I am presuming I can use a Gitlab runner variable but do not see one to us

A: As shell command is not possible yet with variables inside .gitlab-ci.yml, you may edit a build script that get the current tag and build the image inside that script
Both file at the root of your project :
build.sh :
#!/bin/sh

IMAGE="$CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_REF_NAME-$(git describe --abbrev=0 --tags)"

docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
docker build --pull -t $IMAGE .
docker push $IMAGE

.gitlab-ci.yml :
image: docker:latest
services:
  - docker:dind

stages:
  - release

release:
  stage: release
  script:
    - apk update && apk add git
    - ./build.sh

A: There are a lot of predefined variables in Gitlab CI. I think you are looking for CI_COMMIT_TAG.
So you could use it this way:
docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG

So the image would look like registry.example.com/group/project:tag

redpajama_set_name: RedPajamaStackExchange


text:
This is How Facebook's Dislike Button (Empathy Emoji) Will Look Like
Adarsh Verma
Short Bytes: Earlier this week, Facebook CEO Mark Zuckerberg announced that his company is working to bring an option to dislike the posts. The latest revelations indicate that it won't be exactly a dislike button, as that would be very negative. Instead, it would be a collection of the Emojis of some basic human reactions.
If you read comments on some polarizing posts on Facebook, you would soon realise how badly this world needs a dislike button – the ultimate cure and the holy grail of Facebook trolling. Earlier this week, people were ecstatic when Mark Zuckerberg told the world that his company is working on a dislike button.
However, the latest revelations indicate that it won't exactly a dislike button, as that would be very negative. Instead, the Facebook patents show that it would be bringing an Emoji reaction button.
Answering the questions at his live Q&A session at Facebook Headquarters, Mark Zuckerberg said that company is building a new feature. "I think people have asked about the dislike button for many years. Today is a special day because today is the day I can say we're working on it and shipping it," he added.
A recently revealed document from December 23, 2014 – reveals how the empathy Emoji tool might look like. Instead of the usual thumbs down symbol for disliking, users will be able to choose one from a pool of 4-5 Emojis to show their reaction.
According to the patent illustration, Facebook could limit the Emoji option to avoid any kind of clutter and provide the very basic Emojis.
A similar feature is already present in Slack where you can choose the "Add A Reaction" and pick one from a huge list of standard Emoji. But, it doesn't tell you the reaction of the people as a whole because it's very open-ended and shows lots of random reactions.
In his Q&A session, Zuckerberg said that Facebook will be soon testing this feature. Get ready to "unlike" some posts in near future.
What do you think of this upcoming Facebook feature? Tell us in the comments below.
Also read: Zuckerberg Invites Indian PM Narendra Modi to Q&A Session at Facebook Headquarters


Information we collect from MZB website visitors:Visitors to MZB websites can access the website's home page, and browse some areas of the website, without disclosing any personally identifiable information. We do track information provided to us by your browser, including the website you came from (known as the "referring URL"), any MZB online advertisements located on third-party websites that you may have clicked on to access one of the MZB websites, the type of browser you use, the time and date of access, and other information that does not personally identify you. On some of our websites, you must register (see below) to access portions of the website. In addition, we gather information about you that is automatically collected by our Web server, such as your IP address and domain name. MZB may use Web server and browser information to individually customize its offerings and presentations if you submit your personal information.
© Massimo Zanetti Beverage USA, Inc.


"You will find lots of statement generating applications on the net that may automatically generate your bill slide. You would like your invoices to reflect the worth of your small company enterprise. Therefore , it's very important to be aware that the quicker you send out your bills, the faster you'll become paidoff. Invoices are among the most essential files for company owners. Emailed bills are easy to ignore. If you're struggling with creating an appropriate invoice to share with your customer, simply tell us 'd like to generate the bill of your want for absolutely at no charge! You're ready to generate professional looking invoices with all quotes in virtually every language and currency around the planet.