text:
/////////////////////////////////////////////////////////////////////////////////
//
//	vp_InventoryItemsAttribute.cs
//	© Opsive. All Rights Reserved.
//	https://twitter.com/Opsive
//	http://www.opsive.com
//
//	description:	inventory item records foldout editor logic and drawing
//
/////////////////////////////////////////////////////////////////////////////////
#if UNITY_EDITOR

using UnityEditor;
using UnityEngine;
using System.Text;
using System.Collections.Generic;
using System.Globalization;
using System.Collections;

/// <summary>
///
/// </summary>
public class vp_InventoryItemsAttribute : PropertyAttribute
{
}

[CustomPropertyDrawer(typeof(vp_InventoryItemsAttribute))]
public class vp_InventoryItemsDrawer : PropertyDrawer
{

	private string m_InventoryFullCaption = "Failed to add item";
	private string m_InventoryFullMessage = "The inventory did not accept this item. This may be due to either an ITEM CAP or SPACE LIMIT.\n\nYou may want to review inventory settings under 'Item Caps' and 'Space Limit', aswell as the 'Inventory Space' setting of \"{0}\" and (in case that's a UnitBank) its 'Unit' type.";
	private string m_UnitBankAlreadyExistsCaption = "UnitBank already exists";
	private string m_UnitBankAlreadyExistsMessage = "This inventory already has an internal UnitBank for \"{0}\". You may adjust its unit count in the list.";

	private int NO_VALUE = -1;

	protected float m_InitialY = 0.0f;
	protected vp_ItemInstance m_ItemToRemove;
	protected vp_UnitBankInstance m_UnitBankToRemove;

	/// <summary>
	/// override to adjust with our own height. called by Unity
	/// </summary>
	public override float GetPropertyHeight(SerializedProperty prop, GUIContent label)
	{
		return prop.floatValue;
	}

	[SerializeField]
	private static bool m_ItemFoldout;
	[SerializeField]
	private static bool m_CapsFoldout;
	[SerializeField]
	private static bool m_SpaceFoldout;

	/// <summary>
	///
	/// </summary>
	public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label)
	{

		int indentLevelBak = EditorGUI.indentLevel;
		EditorGUI.indentLevel = 1;

		prop.floatValue = DoItemsFoldout(pos, prop);
		EditorGUI.indentLevel = indentLevelBak;

	}

	/// <summary>
	///
	/// </summary>
	protected float DoItemsFoldout(Rect pos, SerializedProperty prop)
	{

		m_InitialY = pos.y;

		pos.height = 16;

		vp_Inventory inventory = ((vp_Inventory)prop.serializedObject.targetObject);

		GUI.backgroundColor = Color.white;

		pos.y +=
		((
		(inventory.ItemInstances.Count > 0) ||
		(inventory.UnitBankInstances.Count > 0) ||
		(inventory.InternalUnitBanks.Count > 0)) ?
		5 : -5);
		pos.x += 20;
		pos.width -= 15;

		// --- draw internal unit banks ---

		for (int v = 0; v < inventory.InternalUnitBanks.Count; v++)
		{

			vp_UnitBankInstance ibank = inventory.InternalUnitBanks[v];

			if ((ibank == null) || (ibank.UnitType == null))
			{
				inventory.InternalUnitBanks.Remove(ibank);
				inventory.Refresh();
				continue;
			}

			string name = ibank.UnitType.ToString();
			name = name.Remove(name.IndexOf(" (")) + "s (Internal UnitBank)";

			int unitCount = inventory.GetItemCount(ibank.UnitType);

			vp_PropertyDrawerUtility.ItemCard(pos,
				((ibank == null) ? null : ibank.UnitType.Icon),
				name,
				((ibank == null) ? null : ibank.UnitType),
				ref unitCount,
				"Units",
				delegate()
				{
					inventory.TrySetUnitCount(ibank.UnitType, unitCount);
				},
				ref NO_VALUE,
				"",
				null,
				delegate()
				{
					m_UnitBankToRemove = ibank;
				});

			pos.y += 21;
		}

		// --- draw item unit bank instances (such as weapons) ---

		for (int v = 0; v < inventory.UnitBankInstances.Count; v++)
		{

			vp_UnitBankInstance bank = inventory.UnitBankInstances[v];

			int unitCount = bank.Count;

			if ((bank == null) || (bank.Type == null))
			{
				inventory.UnitBankInstances.Remove(bank);
				inventory.Refresh();
				continue;
			}

			string name = bank.Type.ToString();

			if (vp_PropertyDrawerUtility.ItemCard(pos,
				((bank == null) ? null : bank.Type.Icon),
				name,
				((bank == null) ? null : bank.Type),
				ref unitCount,
				"Units",
				delegate()
				{
					inventory.TrySetUnitCount(bank, unitCount);
				},
				ref bank.ID,
				"ID",
				null,	// no need to act on value change since it is handled by the ref above
				delegate()
				{
					m_UnitBankToRemove = bank;
				}))
			{
				inventory.ClearItemDictionaries();
				inventory.SetDirty();
			}

			pos.y += 21;

		}

		// --- draw item instances ---

		for (int v = 0; v < inventory.ItemInstances.Count; v++)
		{

			vp_ItemInstance item = inventory.ItemInstances[v];

			if ((item == null) || (item.Type == null))
			{
				inventory.ItemInstances.Remove(item);
				inventory.Refresh();
				continue;
			}

			string name = item.Type.ToString();

			if (vp_PropertyDrawerUtility.ItemCard(pos,
				((item == null) ? null : item.Type.Icon),
				name,
				((item == null) ? null : item.Type),
				ref item.ID,
				"ID",
				null,	// no need to act on value change since it is handled by the ref above
				ref NO_VALUE,
				"",
				null,
				delegate()
				{
					m_ItemToRemove = item;
				}, 45))
			{
				inventory.ClearItemDictionaries();
				inventory.SetDirty();
			}

			pos.y += 21;

		}

		// --- draw 'add object' box ---

		pos.y += 16;

		vp_PropertyDrawerUtility.AddObjectBox(pos, "n ItemType", typeof(vp_ItemType), delegate(Object itemType)
		{

			if (itemType is vp_UnitBankType)
			{
				vp_UnitBankType bank = (vp_UnitBankType)itemType;
				int cap = inventory.GetItemCap((vp_UnitBankType)itemType);

				if ((cap == -1) || (inventory.GetItemCount((vp_UnitBankType)itemType) < cap))
				{
					if (!inventory.TryGiveUnitBank(bank, bank.Capacity, 0))
						EditorUtility.DisplayDialog(m_InventoryFullCaption, string.Format(m_InventoryFullMessage, itemType), "OK");
				}
				else
					EditorUtility.DisplayDialog(m_InventoryFullCaption, string.Format(m_InventoryFullMessage, itemType), "OK");
			}
			else if (itemType is vp_UnitType)
			{
				if (!inventory.HaveInternalUnitBank((vp_UnitType)itemType))
				{
					vp_UnitType unitType = (vp_UnitType)itemType;
					if (!inventory.TryGiveUnits(unitType, 10))
						EditorUtility.DisplayDialog(m_InventoryFullCaption, string.Format(m_InventoryFullMessage, itemType), "OK");
				}
				else
					EditorUtility.DisplayDialog(m_UnitBankAlreadyExistsCaption, string.Format(m_UnitBankAlreadyExistsMessage, itemType), "OK");
			}
			else
			{
				if (!inventory.TryGiveItem((vp_ItemType)itemType, 0))
					EditorUtility.DisplayDialog(m_InventoryFullCaption, string.Format(m_InventoryFullMessage, itemType), "OK");
			}
			EditorUtility.SetDirty(inventory);
			inventory.Refresh();

		});

		pos.y += vp_PropertyDrawerUtility.CalcAddObjectBoxHeight - 5;

		// handle removed items
		if (m_UnitBankToRemove != null)
		{
			inventory.TryRemoveUnitBank(m_UnitBankToRemove);
			m_UnitBankToRemove = null;
		}
		else if (m_ItemToRemove != null)
		{
			inventory.TryRemoveItem(m_ItemToRemove);
			m_ItemToRemove = null;
		}

		return (pos.y - m_InitialY);

	}

}

#endif


text:
""" This is a QGraphicsView for pipeline view, it also holds different
types of graphics items that are only available in the pipeline
view. It only handles GUI-related actions, the rest of the
functionalities are implemented at somewhere else,
e.g. core.vistrails

QGraphicsLinkItem
QGraphicsVersionTextItem
QGraphicsVersionItem
QVersionTreeScene
QVersionTreeView
"""

from PyQt4 import QtCore, QtGui
from core.system import systemType
from core.thumbnails import ThumbnailCache
from gui.base_view import BaseView
from gui.graphics_view import (QInteractiveGraphicsScene,
                               QInteractiveGraphicsView,
                               QGraphicsItemInterface,
                               QGraphicsRubberBandItem)
from gui.qt import qt_super
from gui.theme import CurrentTheme
from gui.version_prop import QVersionPropOverlay
from gui.vis_diff import QVisualDiff

import gui.utils
import math

################################################################################
# QGraphicsLinkItem

class QGraphicsLinkItem(QGraphicsItemInterface, QtGui.QGraphicsPolygonItem):
    """
    QGraphicsLinkItem is a connection shape connecting two versions

    """
    def __init__(self, parent=None, scene=None):
        """ QGraphicsLinkItem(parent: QGraphicsItem,
                              scene: QGraphicsScene) -> QGraphicsLinkItem
        Create the shape, initialize its pen and brush accordingly

        """
        QtGui.QGraphicsPolygonItem.__init__(self, parent, scene)
        self.setFlags(QtGui.QGraphicsItem.ItemIsSelectable)
        self.setZValue(0)
        self.linkPen = CurrentTheme.LINK_PEN
        self.ghosted = False

        # cache link endpoints to improve performance on scene updates
        self.c1 = None
        self.c2 = None
        self.expand = None
        self.collapse = None

    def mousePressEvent(self, event):
        """ mousePressEvent(event: QMouseEvent) -> None

        """
        qt_super(QGraphicsLinkItem, self).mousePressEvent(event)
        self.setSelected(True)

    def mouseReleaseEvent(self, event):
        """ mouseReleaseEvent(event: QMouseEvent) -> None

        """
        qt_super(QGraphicsLinkItem, self).mouseReleaseEvent(event)
        if self.expand:
            self.scene().controller.expand_versions(self.startVersion, self.endVersion)
        elif self.collapse:
            self.scene().controller.collapse_versions(self.endVersion)
        self.setSelected(False)

    def setGhosted(self, ghosted):
        """ setGhosted(ghosted: True) -> None
        Set this link to be ghosted or not

        """
        if self.ghosted <> ghosted:
            self.ghosted = ghosted
            if ghosted:
                self.linkPen = CurrentTheme.GHOSTED_LINK_PEN
            else:
                self.linkPen = CurrentTheme.LINK_PEN

    def setupLink(self, v1, v2, expand=False, collapse=False):
        """ setupLink(v1, v2: QGraphicsVersionItem, compact: bool) -> None
        Setup a line connecting v1 and v2 items

        """
        self.startVersion = min(v1.id, v2.id)
        self.endVersion = max(v1.id, v2.id)

        c1 = v1.sceneBoundingRect().center()
        c2 = v2.sceneBoundingRect().center()

        # check if it is the same geometry
        # improves performance on updates
        if self.c1 != None and self.c2 != None and \
                self.expand != None and self.collapse !=None:
            isTheSame = self.c1 == c1 and \
                self.c2 == c2 and \
                self.expand == expand and \
                self.collapse == collapse
            if isTheSame:
                return

        # update current state
        self.c1 = c1
        self.c2 = c2
        self.collapse = collapse
        self.expand = expand

        # Compute the line of the link and its normal line throught
        # the midpoint
        mainLine = QtCore.QLineF(c1, c2)
        normalLine = mainLine.normalVector()
        normalLine.setLength(CurrentTheme.LINK_SEGMENT_LENGTH)
        dis = (mainLine.pointAt(0.5)-mainLine.p1()+
               normalLine.p1()-normalLine.pointAt(0.5))
        normalLine.translate(dis.x(), dis.y())

        # Generate 2 segments along the main line and 3 segments along
        # the normal line
        if not self.collapse and not self.expand:
            self.lines = [mainLine]
            poly = QtGui.QPolygonF()
            poly.append(self.lines[0].p1())
            poly.append(self.lines[0].p2())
            poly.append(self.lines[0].p1())
            self.setPolygon(poly)
        else:
            self.lines = []

            normalLine = mainLine.normalVector()
            normalLine.setLength(CurrentTheme.LINK_SEGMENT_SQUARE_LENGTH)
            dis = (mainLine.pointAt(0.5)-mainLine.p1()+
                   normalLine.p1()-normalLine.pointAt(0.5))
            normalLine.translate(dis.x(), dis.y())

            gapLine = QtCore.QLineF(mainLine)
            gapLine.setLength(CurrentTheme.LINK_SEGMENT_SQUARE_LENGTH/2)
            gapVector = gapLine.p2()-gapLine.p1()

            # First segment along the main line
            line = QtCore.QLineF(mainLine)
            line.setLength(line.length()/2-CurrentTheme.LINK_SEGMENT_SQUARE_LENGTH/2)
            self.lines.append(QtCore.QLineF(line))

            # Second segment along the main line
            line.translate(line.p2()-line.p1()+gapVector*2)
            self.lines.append(QtCore.QLineF(line))

            # First normal segment in front
            line_t = QtCore.QLineF(normalLine)
            line_t.translate(gapVector*(-1.0))
            self.lines.append(QtCore.QLineF(line_t))

            # Second normal segment in back
            line_b = QtCore.QLineF(normalLine)
            line_b.translate(gapVector)
            self.lines.append(QtCore.QLineF(line_b))

            # Left box
            line = QtCore.QLineF(line_t.p1(),line_b.p1())
            self.lines.append(QtCore.QLineF(line))

            # Right box
            line = QtCore.QLineF(line_t.p2(),line_b.p2())
            self.lines.append(QtCore.QLineF(line))

            # Horizontal plus
            line_h = QtCore.QLineF(normalLine.pointAt(0.2),normalLine.pointAt(0.8))
            self.lines.append(QtCore.QLineF(line_h))

            if self.expand:
                # Vertical plus
                line = QtCore.QLineF(mainLine)
                line.translate((line.p2()-line.p1())/2-gapVector)
                line.setLength(CurrentTheme.LINK_SEGMENT_SQUARE_LENGTH)
                line_v = QtCore.QLineF(line.pointAt(0.2), line.pointAt(0.8))
                self.lines.append(QtCore.QLineF(line_v))

            # Create the poly line for selection and redraw
            poly = QtGui.QPolygonF()
            poly.append(self.lines[0].p1())
            poly.append(self.lines[2].p1())
            poly.append(self.lines[3].p1())
            poly.append(self.lines[1].p2())
            poly.append(self.lines[3].p2())
            poly.append(self.lines[2].p2())
            poly.append(self.lines[0].p1())
            self.setPolygon(poly)

        self.setGhosted(v1.ghosted and v2.ghosted)

    def paint(self, painter, option, widget=None):
        """ paint(painter: QPainter, option: QStyleOptionGraphicsItem,
                  widget: QWidget) -> None
        Peform actual painting of the link

        """
        if self.isSelected():
            painter.setPen(CurrentTheme.LINK_SELECTED_PEN)
        else:
            painter.setPen(self.linkPen)
        for line in self.lines:
            painter.drawLine(line)

    def itemChange(self, change, value):
        """ itemChange(change: GraphicsItemChange, value: QVariant) -> QVariant
        Do not allow link to be selected with version shape

        """
        if change==QtGui.QGraphicsItem.ItemSelectedChange and value.toBool():
            return QtCore.QVariant(False)
        return QtGui.QGraphicsPolygonItem.itemChange(self, change, value)

##############################################################################
# QGraphicsVerstionTextItem

class QGraphicsVersionTextItem(QGraphicsItemInterface, QtGui.QGraphicsTextItem):
    """
    QGraphicsVersionTextItem is an editable text item that appears on top of
    a QGraphicsVersionItem to allow the tag to be changed

    """
    def __init__(self, parent=None, scene=None):
        """ QGraphicsVersionTextItem(parent: QGraphicsVersionItem,
        scene: QGraphicsScene) -> QGraphicsVersionTextItem

        Create the shape, intialize its drawing style

        """
        QtGui.QGraphicsTextItem.__init__(self, parent, scene)
        self.timer = None
        self.isEditable = None
        self.setEditable(False)
        self.setFont(CurrentTheme.VERSION_FONT)
        self.setTextWidth(CurrentTheme.VERSION_LABEL_MARGIN[0])
        self.setDefaultTextColor(CurrentTheme.VERSION_LABEL_COLOR)
        self.centerX = 0.0
        self.centerY = 0.0
        self.label = ''
        self.isTag = True
        self.updatingTag = False

    def setEditable(self, editable=True):
        if self.timer:
            self.timer.stop()
            self.timer = None
        if editable == self.isEditable:
            return
        self.isEditable = editable
        if editable:
            self.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction)
        else:
            if self.textCursor():
                c = self.textCursor()
                c.clearSelection()
                self.setTextCursor(c)
            self.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)

    def setEditableLater(self):
        self.timer = QtCore.QTimer(self)
        self.timer.setSingleShot(True)
        self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.setEditable)
        self.timer.start(QtGui.QApplication.doubleClickInterval() + 5)

    def setGhosted(self, ghosted):
        if ghosted:
            self.setDefaultTextColor(CurrentTheme.GHOSTED_VERSION_LABEL_COLOR)
        else:
            self.setDefaultTextColor(CurrentTheme.VERSION_LABEL_COLOR)

    def changed(self, x, y, label, tag=True):
        """ changed(x: float, y: float, label: str) -> None
        Change the position and text label from outside the editor

        """
        if self.centerX <> x or self.centerY <> y or self.label <> label:
            self.centerX = x
            self.centerY = y
            self.label = label
            self.isTag = tag
            if self.isTag:
                self.setFont(CurrentTheme.VERSION_FONT)
            else:
                self.setFont(CurrentTheme.VERSION_DESCRIPTION_FONT)
            self.reset()

    def reset(self):
        """ reset() -> None
        Resets the text label, width, and positions to the stored values

        """
        self.setPlainText(self.label)
        self.setEditable(False)
        if (len(str(self.label)) > 0):
            self.setTextWidth(-1)
        else:
            self.setTextWidth(CurrentTheme.VERSION_LABEL_MARGIN[0])

        if self.isTag:
            self.setFont(CurrentTheme.VERSION_FONT)
        else:
            self.setFont(CurrentTheme.VERSION_DESCRIPTION_FONT)
        self.updatePos()
        self.parentItem().updateWidthFromLabel()

    def updatePos(self):
        """ updatePos() -> None
        Center the text, by default it uses the upper left corner

        """
        self.setPos(self.centerX-self.boundingRect().width()/2.0,
                    self.centerY-self.boundingRect().height()/2.0)

    def keyPressEvent(self, event):
        """ keyPressEvent(event: QEvent) -> None
        Enter and Return keys signal a change in the label.  Other keys
        update the position and size of the parent ellipse during key entry.

        """
        if event.key() in [QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return]:
            self.updatingTag = True
            if (self.label == str(self.toPlainText()) or
                not self.scene().controller.update_current_tag(str(self.toPlainText()))):
                self.reset()
            self.updatingTag = False
            event.ignore()
            self.clearFocus()
            return
        qt_super(QGraphicsVersionTextItem, self).keyPressEvent(event)
        if (len(str(self.toPlainText())) > 0):
            self.setTextWidth(-1)
        self.updatePos()
        self.parentItem().updateWidthFromLabel()

    def focusOutEvent(self, event):
        """ focusOutEvent(event: QEvent) -> None
        Update the tag if the text has changed

        """
        qt_super(QGraphicsVersionTextItem, self).focusOutEvent(event)
        if not self.updatingTag and QtCore.QString.compare(self.label, self.toPlainText()) != 0:
            self.updatingTag = True
            if (self.label == str(self.toPlainText()) or
                not self.scene().controller.update_current_tag(str(self.toPlainText()))):
                self.reset()
            self.updatingTag = False

##############################################################################
# QGraphicsVersionItem

class QGraphicsVersionItem(QGraphicsItemInterface, QtGui.QGraphicsEllipseItem):
    """
    QGraphicsVersionItem is the version shape holding version id and
    label

    """
    def __init__(self, parent=None, scene=None):
        """ QGraphicsVersionItem(parent: QGraphicsItem, scene: QGraphicsScene)
                                -> QGraphicsVersionItem
        Create the shape, initialize its pen and brush accordingly

        """
        QtGui.QGraphicsEllipseItem.__init__(self, parent, scene)
        self.setZValue(1)
        self.setAcceptDrops(True)
        self.setFlags(QtGui.QGraphicsItem.ItemIsSelectable)
        self._versionPenNormal = CurrentTheme.VERSION_PEN
        self._versionPen = CurrentTheme.VERSION_PEN
        self._versionBrush = CurrentTheme.VERSION_USER_BRUSH
        self.id = -1
        self.label = ''
        self.descriptionLabel = ''
        self.dragging = False
        self.ghosted = False
        self.updatePainterState()

        # self.rank is a positive number that determines the
        # saturation of the node. Two version nodes might have the
        # same rank if they were created by different users
        # self.max_rank is the maximum rank for that version class
        self.rank = -1
        self.max_rank = -1

        # Editable text item that remains hidden unless the version is selected
        self.text = QGraphicsVersionTextItem(self)

        # Need a timer to start a drag to avoid stalls on QGraphicsView
        self.dragTimer = QtCore.QTimer()
        self.dragTimer.setSingleShot(True)
        self.dragTimer.connect(self.dragTimer,
                               QtCore.SIGNAL('timeout()'),
                               self.startDrag)

        self.dragPos = QtCore.QPoint()

    def _get_versionPen(self):
        return self._versionPen
    def _set_versionPen(self, pen):
        self._versionPen = pen
        self.updatePainterState()
    versionPen = property(_get_versionPen, _set_versionPen)

    def _get_versionBrush(self):
        return self._versionBrush
    def _set_versionBrush(self, brush):
        self._versionBrush = brush
        self.updatePainterState()
    versionBrush = property(_get_versionBrush, _set_versionBrush)

    def itemChange(self, change, value):
        if change == QtGui.QGraphicsItem.ItemSelectedHasChanged:
            if self.isSelected():
                self.versionPen = CurrentTheme.VERSION_SELECTED_PEN
                self.text.setEditableLater()
            else:
                self.versionPen = self._versionPenNormal
                self.text.setEditable(False)
            self.updatePainterState()
        return QtGui.QGraphicsItem.itemChange(self, change, value)

    def setGhosted(self, ghosted=True):
        """ setGhosted(ghosted: True) -> None
        Set this version to be ghosted or not

        """
        if self.ghosted <> ghosted:
            self.ghosted = ghosted
            self.text.setGhosted(ghosted)
            if ghosted:
                self._versionPenNormal = CurrentTheme.GHOSTED_VERSION_PEN
                self._versionBrush = CurrentTheme.GHOSTED_VERSION_USER_BRUSH
            else:
                self._versionPenNormal = CurrentTheme.VERSION_PEN
                self._versionBrush = CurrentTheme.VERSION_USER_BRUSH
            if not self.isSelected():
                self._versionPen = self._versionPenNormal
            self.updatePainterState()

    def update_color(self, isThisUs, new_rank, new_max_rank, new_ghosted):
        """ update_color(isThisUs: bool,
                         new_rank, new_max_rank: int) -> None

        If necessary, update the colors of this version node based on
        who owns the node and new ranks

        NOTE: if username changes during execution, this might break.
        """
        if (new_rank == self.rank and new_max_rank == self.max_rank and
            new_ghosted == self.ghosted):
            # nothing changed
            return
        self.setGhosted(new_ghosted)
        self.rank = new_rank
        self.max_rank = new_max_rank
        if not self.ghosted:
            if isThisUs:
                brush = CurrentTheme.VERSION_USER_BRUSH
            else:
                brush = CurrentTheme.VERSION_OTHER_BRUSH
            sat = float(new_rank+1) / new_max_rank
            (h, s, v, a) = brush.color().getHsvF()
            newHsv = (h, s*sat, v+(1.0-v)*(1-sat), a)
            self.versionBrush = QtGui.QBrush(QtGui.QColor.fromHsvF(*newHsv))

    def setSaturation(self, isThisUser, sat):
        """ setSaturation(isThisUser: bool, sat: float) -> None
        Set the color of this version depending on whose is the user
        and its saturation

        """
        if not self.ghosted:
            if isThisUser:
                brush = CurrentTheme.VERSION_USER_BRUSH
            else:
                brush = CurrentTheme.VERSION_OTHER_BRUSH

            (h, s, v, a) = brush.color().getHsvF()
            newHsv = (h, s*sat, v+(1.0-v)*(1-sat), a)
            self.versionBrush = QtGui.QBrush(QtGui.QColor.fromHsvF(*newHsv))

    def updateWidthFromLabel(self):
        """ updateWidthFromLabel() -> None
        Change the width of the ellipse based on a temporary change in the label

        """
        prevWidth = self.rect().width()
        width = self.text.boundingRect().width() + \
            CurrentTheme.VERSION_LABEL_MARGIN[0] - 4
        r = self.rect()
        r.setX(r.x()+(prevWidth-width)/2.0)
        r.setWidth(width)
        self.setRect(r)
        self.update()

    def setupVersion(self, node, action, tag, description):
        """ setupPort(node: DotNode,
                      action: DBAction,
                      tag: str,
                      description: str) -> None
        Update the version dimensions and id

        """
        # Lauro:
        # what was this hacking??? the coordinates inside
        # the input "node" should come to this point ready. This is
        # not the point to do layout calculations (e.g. -node.p.y/2)

        # Carlos:
        # This is not layout as much as dealing with the way Qt
        # specifies rectangles. Besides, moving this back here reduces
        # code duplication, and allows customized behavior for
        # subclasses.

        rect = QtCore.QRectF(node.p.x-node.width/2.0,
                             node.p.y-node.height/2.0,
                             node.width,
                             node.height)
        validLabel = True
        if tag is None:
            label = ''
            validLabel=False
        else:
            label = tag

        self.id = node.id
        self.label = label
        if description is None:
            self.descriptionLabel = ''
        else:
            self.descriptionLabel = description
        if validLabel:
            textToDraw=self.label
        else:
            textToDraw=self.descriptionLabel

        if (ThumbnailCache.getInstance().conf.mouseHover and
            action and action.thumbnail is not None):
            fname = ThumbnailCache.getInstance().get_abs_name_entry(action.thumbnail)
            self.setToolTip('<img src="%s" height="128" border="1"/>'%fname)
        else:
            self.setToolTip('')
        self.text.changed(node.p.x, node.p.y, textToDraw, validLabel)
        self.setRect(rect)

    def boundingRect(self):
        """ boundingRect() -> QRectF
        Add a padded space to avoid un-updated area
        """
        return self.rect().adjusted(-2, -2, 2, 2)

    def paint(self, painter, option, widget=None):
        option.state &= ~QtGui.QStyle.State_Selected
        QtGui.QGraphicsEllipseItem.paint(self, painter, option, widget)

    def updatePainterState(self):
        self.setPen(self._versionPen)
        self.setBrush(self._versionBrush)

    def mousePressEvent(self, event):
        """ mousePressEvent(event: QMouseEvent) -> None
        Start dragging a version to someplaces...

        """
        if event.button()==QtCore.Qt.LeftButton:
            self.dragging = True
            self.dragPos = QtCore.QPoint(event.screenPos())
        return QtGui.QGraphicsEllipseItem.mousePressEvent(self, event)

    def mouseMoveEvent(self, event):
        """ mouseMoveEvent(event: QMouseEvent) -> None
        Now set the timer preparing for dragging. Must use a timer in
        junction with QDrag in order to avoid problem updates stall of
        QGraphicsView, especially on Linux

        """
        if (self.dragging and
            (event.screenPos()-self.dragPos).manhattanLength()>2):
            self.dragging = False
            #the timer has undesirable effects on Windows
            if systemType not in ['Windows', 'Microsoft']:
                self.dragTimer.start(1)
            else:
                self.startDrag()
        QtGui.QGraphicsEllipseItem.mouseMoveEvent(self, event)
        # super(QGraphicsVersionItem, self).mouseMoveEvent(event)

    def startDrag(self):
        """ startDrag() -> None
        Start the drag of QDrag

        """
        data = QtCore.QMimeData()
        data.versionId = self.id
        data.controller = self.scene().controller
        drag = QtGui.QDrag(self.scene().views()[0])
        drag.setMimeData(data)
        drag.setPixmap(CurrentTheme.VERSION_DRAG_PIXMAP)
        drag.start()

    def mouseReleaseEvent(self, event):
        """ mouseReleaseEvent(event: QMouseEvent) -> None
        Cancel the drag

        """
        self.dragging = False
        QtGui.QGraphicsEllipseItem.mouseReleaseEvent(self, event)

    def dragEnterEvent(self, event):
        """ dragEnterEvent(event: QDragEnterEvent) -> None
        Capture version-to-version drag-and-drop

        """
        data = event.mimeData()
        if (hasattr(data, 'versionId') and
            hasattr(data, 'controller') and
            data.versionId!=self.id):
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        data = event.mimeData()
        if (hasattr(data, 'versionId') and hasattr(data, 'controller') and
            data.controller==self.scene().controller):
            event.accept()
            self.scene().emit(QtCore.SIGNAL('diffRequested(int,int)'),
                              data.versionId, self.id)
            # visDiff = QVisualDiff(self.scene().controller.vistrail,
            #                       data.versionId,
            #                       self.id,
            #                       self.scene().controller,
            #                       self.scene().views()[0])
            # visDiff.show()
        else:
            event.ignore()

    def perform_analogy(self):
        sender = self.scene().sender()
        analogy_name = str(sender.text())
        # selectedItems = self.scene().selectedItems()
        controller = self.scene().controller
        print "calling perform analogy", analogy_name, self.id
        # for item in selectedItems:
        controller.perform_analogy(analogy_name, self.id)

    def show_raw_pipeline(self):
        self.scene().emit_selection = False
        for item in self.scene().selectedItems():
            item.setSelected(False)
        self.setSelected(True)
        self.scene().emit_selection = True
        self.scene().emit(
            QtCore.SIGNAL('versionSelected(int,bool,bool,bool,bool)'),
            self.id, True, False, True, True)

    def construct_from_root(self):
        self.scene().emit_selection = False
        for item in self.scene().selectedItems():
            item.setSelected(False)
        self.setSelected(True)
        self.scene().emit_selection = True
        self.scene().emit(
            QtCore.SIGNAL('versionSelected(int,bool,bool,bool,bool)'),
            self.id, True, True, True, True)

    def contextMenuEvent(self, event):
        """contextMenuEvent(event: QGraphicsSceneContextMenuEvent) -> None
        Captures context menu event.

        """
        controller = self.scene().controller
        menu = QtGui.QMenu()
        raw_action = QtGui.QAction("Display raw pipeline", self.scene())
        from_root_action = QtGui.QAction("Construct from root", self.scene())
        QtCore.QObject.connect(raw_action,
                               QtCore.SIGNAL("triggered()"),
                               self.show_raw_pipeline)
        QtCore.QObject.connect(from_root_action,
                               QtCore.SIGNAL("triggered()"),
                               self.construct_from_root)
        menu.addAction(raw_action)
        menu.addAction(from_root_action)
        if len(controller.analogy) > 0:
            analogies = QtGui.QMenu("Perform analogy...")
            for title in sorted(controller.analogy.keys()):
                act = QtGui.QAction(title, self.scene())
                analogies.addAction(act)
                QtCore.QObject.connect(act,
                                       QtCore.SIGNAL("triggered()"),
                                       self.perform_analogy)
            menu.addMenu(analogies)
        menu.exec_(event.screenPos())

    def mouseDoubleClickEvent(self, event):
        # QtGui.QGraphicsEllipseItem.mouseDoubleClickEvent(self, event)
        event.accept()
        self.scene().double_click(self.id)

class QVersionTreeScene(QInteractiveGraphicsScene):
    """
    QVersionTree inherits from QInteractiveGraphicsScene to keep track
    of the version scenes, i.e. versions, connections, etc.

    """

    def __init__(self, parent=None):
        """ QVersionTree(parent: QWidget) -> QVersionTree
        Initialize the graphics scene with no shapes

        """
        QInteractiveGraphicsScene.__init__(self, parent)
        self.setBackgroundBrush(CurrentTheme.VERSION_TREE_BACKGROUND_BRUSH)
        self.setSceneRect(QtCore.QRectF(-5000, -5000, 10000, 10000))
        self.versions = {}  # id -> version gui object
        self.edges = {}     # (sourceVersion, targetVersion) -> edge gui object
        self.controller = None
        self.fullGraph = None
        self.timer = QtCore.QBasicTimer()
        self.animation_step = 1
        self.num_animation_steps = 1
        self.emit_selection = True
        self.select_by_click = True
        self.connect(self, QtCore.SIGNAL("selectionChanged()"),
                     self.selectionChanged)

    def addVersion(self, node, action, tag, description):
        """ addModule(node, action: DBAction, tag: str, description: str)
                -> None
        Add a module to the scene.

        """
        versionShape = QGraphicsVersionItem(None)
        versionShape.setupVersion(node, action, tag, description)
        self.addItem(versionShape)
        self.versions[node.id] = versionShape

    def removeVersion(self, v):
        """ addLink(v: integer) -> None
        Remove version from scene and mapping

        """
        versionShape = self.versions[v]
        self.removeItem(versionShape)
        self.versions.pop(v)

    def addLink(self, guiSource, guiTarget, expand, collapse):
        """ addLink(v1, v2: QGraphicsVersionItem) -> None
        Add a link to the scene

        """
        linkShape = QGraphicsLinkItem()
        linkShape.setupLink(guiSource, guiTarget, expand, collapse)
        self.addItem(linkShape)
        self.edges[(guiSource.id, guiTarget.id)] = linkShape

    def removeLink(self, source, target):
        """ removeLink(v1, v2: integers) -> None
        Remove link from scene and mapping

        """
        linkShape = self.edges[(source,target)]
        self.removeItem(linkShape)
        self.edges.pop((source, target))

    def clear(self):
        """ clear() -> None
        Clear the whole scene

        """
        self.versions = {}
        self.clearItems()

    def adjust_version_colors(self, controller):
        """ adjust_version_colors(controller: VistrailController) -> None
        Based on the controller to set version colors

        """
        currentUser = controller.vistrail.getUser()
        ranks = {}
        ourMaxRank = 0
        otherMaxRank = 0
        am = controller.vistrail.actionMap
        for nodeId in sorted(self.versions.keys()):
            if nodeId!=0:
                nodeUser = am[nodeId].user
                if nodeUser==currentUser:
                    ranks[nodeId] = ourMaxRank
                    ourMaxRank += 1
                else:
                    ranks[nodeId] = otherMaxRank
                    otherMaxRank += 1
        for (nodeId, item) in self.versions.iteritems():
            if nodeId == 0:
                item.setGhosted(True)
                continue
            nodeUser = am[nodeId].user
            if controller.search and nodeId!=0:
                ghosted = not controller.search.match(controller.vistrail,
                                                      am[nodeId])
            else:
                ghosted = False

            #item.setGhosted(ghosted) # we won't set it now so we can check if
                                      # the state changed in update_color
            if nodeUser==currentUser:
                max_rank = ourMaxRank
            else:
                max_rank = otherMaxRank
#             max_rank = ourMaxRank if nodeUser==currentUser else otherMaxRank
            item.update_color(nodeUser==currentUser,
                              ranks[nodeId],
                              max_rank, ghosted)
        for (version_from, version_to), link in self.edges.iteritems():
            if self.versions[version_from].ghosted and \
                    self.versions[version_to].ghosted:
                link.setGhosted(True)
            else:
                link.setGhosted(False)

    def update_scene_single_node_change(self, controller, old_version, new_version):
        """ update_scene_single_node_change(controller: VistrailController,
        old_version, new_version: int) -> None

        Faster alternative to setup_scene when a single version is
        changed. When this is called, we know that both old_version
        and new_version don't have tags associated, so no layout
        changes happen

        """
        # self.setupScene(controller)

        # we need to call this every time because version ranks might
        # change
        self.adjust_version_colors(controller)

        # update version item
        v = self.versions[old_version]
        old_desc = controller.vistrail.get_description(old_version)
        new_desc = controller.vistrail.get_description(new_version)
        if old_desc != new_desc:
            v.descriptionLabel = new_desc
            v.text.changed(v.text.centerX, v.text.centerY, new_desc, False)
            v.updateWidthFromLabel()
        self.versions[new_version] = v
        del self.versions[old_version]
        v.id = new_version

        # update link items
        dst = controller._current_terse_graph.edges_from(new_version)
        for eto, _ in dst:
            edge = self.edges[(old_version, eto)]
            edge.setupLink(self.versions[new_version],
                           self.versions[eto],
                           self.fullGraph.parent(eto) != new_version,
                           False) # We shouldn't ever need a collapse here
            self.edges[(new_version, eto)] = edge
            del self.edges[(old_version, eto)]

        src = controller._current_terse_graph.edges_to(new_version)
        for efrom, _ in src:
            edge = self.edges[(efrom, old_version)]
            edge.setupLink(self.versions[efrom],
                           self.versions[new_version],
                           self.fullGraph.parent(new_version) != efrom,
                           False) # We shouldn't ever need a collapse here
            self.edges[(efrom, new_version)] = edge
            del self.edges[(efrom, old_version)]

    def setupScene(self, controller, select_node=True):
        """ setupScene(controller: VistrailController) -> None
        Construct the scene to view a version tree

        """
        import time
        t = time.clock()

        tClearRefine = time.clock()

        # Clean the previous scene
        # self.clear()

        self.select_by_click = False
        self.controller = controller

        # perform graph layout
        (tree, self.fullGraph, layout) = \
            controller.refine_graph(float(self.animation_step)/
                                    float(self.num_animation_steps))

        tClearRefine = time.clock() - tClearRefine

        # compute nodes that should be removed
        # O(n  * (hashmap query key time)) on
        # where n is the number of current
        # nodes in the scene
        removeNodeSet = set(i for i in self.versions
                            if not i in tree.vertices)

        # compute edges to be removed
        # O(n * (hashmap query key time))
        # where n is the number of current
        # edges in the scene
        removeEdgeSet = set((s, t) for (s, t) in self.edges
                            if (s in removeNodeSet or
                                t in removeNodeSet or
                                not tree.has_edge(s, t)))

        # loop on the nodes of the tree
        vistrail = controller.vistrail
        tm = vistrail.get_tagMap()
        am = vistrail.actionMap
        last_n = vistrail.getLastActions(controller.num_versions_always_shown)

        self.emit_selection = False
        for node in layout.nodes.itervalues():

            # version id
            v = node.id

            # version tag
            tag = tm.get(v, None)
            action = am.get(v, None)
            description = vistrail.get_description(v)

            # if the version gui object already exists...
            if v in self.versions:
                versionShape = self.versions[v]
                versionShape.setupVersion(node, action, tag, description)
            else:
                self.addVersion(node, action, tag, description)
            if select_node:
                self.versions[v].setSelected(v == controller.current_version)

        self.emit_selection = True
        self.selectionChanged()

        # remove gui edges from scene
        for (v1, v2) in removeEdgeSet:
            self.removeLink(v1,v2)

        # remove gui nodes from scene
        for v in removeNodeSet:
            self.removeVersion(v)

        tCreate = time.clock()

        # adjust the colors
        self.adjust_version_colors(controller)

        # Add or update links
        for source in tree.vertices.iterkeys():
            eFrom = tree.edges_from(source)
            for (target, aux) in eFrom:
                guiSource = self.versions[source]
                guiTarget = self.versions[target]
                sourceChildren = [to for (to, _) in
                                  self.fullGraph.adjacency_list[source]
                                  if (to in am) and not vistrail.is_pruned(to)]
                targetChildren = [to for (to, _) in
                                  self.fullGraph.adjacency_list[target]
                                  if (to in am) and not vistrail.is_pruned(to)]
                expand = self.fullGraph.parent(target)!=source
                collapse = (self.fullGraph.parent(target)==source and # No in betweens
                            len(targetChildren) == 1 and # target is not a leaf or branch
                            target != controller.current_version and # target is not selected
                            target not in tm and # target has no tag
                            target not in last_n and # not one of the last n modules
                            (source in tm or # source has a tag
                             source == 0 or # source is root node
                             len(sourceChildren) > 1 or # source is branching node
                             source == controller.current_version)) # source is selected
                if self.edges.has_key((source,target)):
                    linkShape = self.edges[(source,target)]
                    linkShape.setupLink(guiSource, guiTarget,
                                        expand, collapse)
                else:
                    #print "add link %d %d" % (source, target)
                    self.addLink(guiSource, guiTarget,
                                 expand, collapse)

        tCreate = time.clock() - tCreate

        # Update bounding rects and fit to all view
        tUpdate = time.clock()
        if not self.controller.animate_layout:
            self.updateSceneBoundingRect()
        elif not self.timer.isActive():
            self.timer.start(0, self)
        tUpdate = time.clock() - tUpdate

        self.select_by_click = True

        t = time.clock() - t
        # print "time in msec to setupScene total: %f  refine %f  layout %f  create %f" % (t, tClearRefine, tCreate)

    def timerEvent(self, event):
        """ timerEvent(event: QTimerEvent) -> None

        Start up a timer for animating tree drawing events
        """
        if event.timerId() == self.timer.timerId():
            self.animation_step += 1
            if self.animation_step >= self.num_animation_steps:
                self.animation_step = 1
                self.timer.stop()
                self.controller.animate_layout = False
            self.setupScene(self.controller)
            self.update()
        else:
            qt_super(QVersionTreeScene, self).timerEvent(event)

    def keyPressEvent(self, event):
        """ keyPressEvent(event: QKeyEvent) -> None
        Capture 'Del', 'Backspace' for pruning versions when not editing a tag

        """
        selectedItems = self.selectedItems()
        versions = [item.id for item in selectedItems
                    if type(item)==QGraphicsVersionItem
                    and not item.text.hasFocus()]
        if (self.controller and len(versions)>0 and
            event.key() in [QtCore.Qt.Key_Backspace, QtCore.Qt.Key_Delete]):
            event.accept()
            versions = [item.id for item in selectedItems]
            res = gui.utils.show_question("VisTrails",
                                           "Are you sure that you want to "
                                           "prune the selected version(s)?",
                                           [gui.utils.YES_BUTTON,
                                            gui.utils.NO_BUTTON],
                                           gui.utils.NO_BUTTON)
            if res == gui.utils.YES_BUTTON:
                self.controller.prune_versions(versions)
        else:
            qt_super(QVersionTreeScene, self).keyPressEvent(event)

    def selectionChanged(self):
        if not self.emit_selection:
            return

        selected_items = self.selectedItems()
        if len(selected_items) == 1:
            # emit versionSelected selected_id
            self.emit(QtCore.SIGNAL('versionSelected(int,bool,bool,bool,bool)'),
                      selected_items[0].id, self.select_by_click,
                      True, False, False)
        else:
            # emit versionSelected -1
            for item in selected_items:
                if item.text.isEditable:
                    item.text.setEditable(False)
            self.emit(QtCore.SIGNAL('versionSelected(int,bool,bool,bool,bool)'),
                      -1, self.select_by_click, True, False, False)

        if len(selected_items) == 2:
            self.emit(
                QtCore.SIGNAL('twoVersionsSelected(int, int)'),
                selected_items[0].id, selected_items[1].id)

    def double_click(self, version_id):
        self.mouseGrabberItem().ungrabMouse()
        self.emit(QtCore.SIGNAL('versionSelected(int,bool,bool,bool,bool)'),
                  version_id, self.select_by_click, True, False, True)

class QVersionTreeView(QInteractiveGraphicsView, BaseView):
    """
    QVersionTreeView inherits from QInteractiveGraphicsView that will
    handle drawing of versions layout output from Dotty

    """

    def __init__(self, parent=None):
        """ QVersionTreeView(parent: QWidget) -> QVersionTreeView
        Initialize the graphics view and its properties

        """
        QInteractiveGraphicsView.__init__(self, parent)
        BaseView.__init__(self)
        self.controller = None
        self.set_title('Version Tree')
        self.setScene(QVersionTreeScene(self))
        self.versionProp = QVersionPropOverlay(self, self.viewport())
        self.versionProp.hide()

    def set_default_layout(self):
        from gui.collection.workspace import QWorkspaceWindow
        from gui.version_prop import QVersionProp
        self.set_palette_layout(
            {QtCore.Qt.LeftDockWidgetArea: QWorkspaceWindow,
             QtCore.Qt.RightDockWidgetArea: QVersionProp,
             })

    def set_action_links(self):
        self.action_links = \
            {
             'publishWeb' : ('version_changed', self.check_publish_db),
             'publishPaper': ('version_changed', self.check_publish),
             'redo': ('version_changed', self.can_redo),
             'undo': ('version_changed', self.can_undo),
             'execute': ('pipeline_changed', self.can_execute)
            }

    def set_action_defaults(self):
        self.action_defaults['execute'] = \
            [('setEnabled', True, self.set_action_execute_default)]

    def set_action_execute_default(self):
        if self.controller:
            if self.controller.current_pipeline:
                return len(self.controller.current_pipeline.modules) > 0
        return False

    def check_publish_db(self, versionId):
        loc = self.controller.locator
        result = False
        if hasattr(loc,'host'):
            result = True
        return result and self.check_publish(versionId)

    def check_publish(self, versionId):
        return versionId > 0

    def can_redo(self, versionId):
        return self.controller and self.controller.can_redo()

    def can_undo(self, versionId):
        return self.controller and self.controller.can_undo()

    def can_execute(self, pipeline):
        return pipeline is not None and len(pipeline.modules) > 0

    def execute(self):
        res = self.controller.execute_current_workflow()
        from gui.vistrails_window import _app
        if len(res[0][0].errors) > 0:
            _app.qactions['pipeline'].trigger()
        _app.notify('execution_updated')

    def publish_to_web(self):
        from gui.publishing import QVersionEmbed
        panel = QVersionEmbed.instance()
        panel.switchType('Wiki')
        panel.set_visible(True)

    def publish_to_paper(self):
        from gui.publishing import QVersionEmbed
        panel = QVersionEmbed.instance()
        panel.switchType('Latex')
        panel.set_visible(True)

    def selectModules(self):
        """ selectModules() -> None
        Overrides parent class to disable text items if you click on background

        """
        if self.canSelectRectangle:
            br = self.selectionBox.sceneBoundingRect()
        else:
            br = QtCore.QRectF(self.startSelectingPos,
                               self.startSelectingPos)
        items = self.scene().items(br)
        if len(items)==0 or items==[self.selectionBox]:
            for item in self.scene().selectedItems():
                if type(item) == gui.version_view.QGraphicsVersionItem:
                    item.text.clearFocus()
        qt_super(QVersionTreeView, self).selectModules()

    def set_title(self, title):
        BaseView.set_title(self, title)
        self.setWindowTitle(title)

    def set_controller(self, controller):
        oldController = self.controller
        if oldController != controller:
            if oldController != None:
                self.disconnect(oldController,
                                QtCore.SIGNAL('vistrailChanged()'),
                                self.vistrailChanged)
                self.disconnect(oldController,
                                QtCore.SIGNAL('invalidateSingleNodeInVersionTree'),
                                self.single_node_changed)
                self.disconnect(oldController,
                                QtCore.SIGNAL('notesChanged()'),
                                self.notesChanged)
            self.controller = controller
            self.scene().controller = controller
            self.connect(controller,
                         QtCore.SIGNAL('vistrailChanged()'),
                         self.vistrailChanged)
            self.connect(controller,
                         QtCore.SIGNAL('invalidateSingleNodeInVersionTree'),
                         self.single_node_changed)
            self.connect(controller,
                         QtCore.SIGNAL("notesChanged()"),
                         self.notesChanged)
            if controller:
                self.versionProp.updateController(controller)
                self.scene().setupScene(controller)
                # self.vistrailChanged()
                # self.versionProp.updateController(controller)
                # self.versionView.versionProp.updateController(controller)

    def vistrailChanged(self):
        """ vistrailChanged() -> None
        An action was performed on the current vistrail

        """
        from gui.vistrails_window import _app
        select_node = True
        if _app._previous_view and _app._previous_view.window() != self.window():
            select_node = False
        self.scene().setupScene(self.controller, select_node)
        if self.controller and self.controller.reset_version_view:
            self.scene().fitToAllViews()
        if self.controller:
            # self.versionProp.updateVersion(self.controller.current_version)
            self.versionProp.updateVersion(self.controller.current_version)
        self.emit(QtCore.SIGNAL("vistrailChanged()"))

    def single_node_changed(self, old_version, new_version):
        """ single_node_changed(old_version, new_version)
        Handle single node change on version tree by not recomputing
        entire scene.

        """
        self.scene().update_scene_single_node_change(self.controller,
                                                     old_version,
                                                     new_version)
        if self.controller and self.controller.reset_version_view:
            self.scene().fitToAllViews()
        if self.controller:
            # self.versionProp.updateVersion(self.controller.current_version)
            self.versionProp.updateVersion(self.controller.current_version)
        self.emit(QtCore.SIGNAL("vistrailChanged()"))

    def notesChanged(self):
        """ notesChanged() -> None
        The notes for the current vistrail version changed

        """
        if self.controller:
            self.versionProp.updateVersion(self.controller.current_version)

    def select_current_version(self):
        self.scene().setupScene(self.controller)
################################################################################

redpajama_set_name: RedPajamaGithub


text:
namespace Ostrich
{
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Diagnostics;
    using Newtonsoft.Json;
    using Ostrich.Logging;
    using Ostrich.Util;

    public class Stats : StatsCollection
    {
        private static readonly ILog Logger = LogProvider.GetCurrentClassLogger();

        private static readonly ConcurrentDictionary<string, StatsCollection> NamedCollections = new ConcurrentDictionary<string, StatsCollection>();

        static Stats()
        {
            var stats = new Stats();
            NamedCollections[string.Empty] = stats;

            try
            {
                var heapBytes = new PerformanceCounter(".NET CLR Memory", "# Bytes in all Heaps", "_Global_");
                MachineGauge("clr.heap_mb_bytes", () => heapBytes.NextValue() / 1000);

                var counter = new PerformanceCounter(".NET CLR Memory", "% Time in GC", "_Global_");
                MachineGauge("clr.time_in_gc", () => counter.NextValue());

                var exceptions = new PerformanceCounter(".NET CLR Exceptions", "# of Exceps thrown / sec", "_Global_");
                MachineGauge("clr.exceptions_sec", () => exceptions.NextValue());

                var cpu = new PerformanceCounter("Processor", "% User Time", "_Total");
                MachineGauge("cpu.user_time", () => cpu.NextValue());

                var cacheTotalMemory = new PerformanceCounter("ASP.NET Applications", "Cache % Machine Memory Limit Used", "__Total__");
                MachineGauge("aspnet.cache.machine_memory_limit_pct", () => cacheTotalMemory.NextValue());

                var cacheProcessMemory = new PerformanceCounter("ASP.NET Applications", "Cache % Process Memory Limit Used", "__Total__");
                MachineGauge("aspnet.cache.process_memory_limit_pct", () => cacheProcessMemory.NextValue());

                var cacheRatio = new PerformanceCounter("ASP.NET Applications", "Cache Total Hit Ratio", "__Total__");
                MachineGauge("aspnet.cache.hit_ratio", () => cacheRatio.NextValue());

                var cacheTrims = new PerformanceCounter("ASP.NET Applications", "Cache Total Trims", "__Total__");
                MachineGauge("aspnet.cache.trims", () => cacheTrims.NextValue());
            }
            catch (Exception e)
            {
                Logger.WarnException("Could not read performance counters so the performance counter gauges will not be available. " +
                            " The current process probably does not have the right permissions.", e);
            }
        }

        public static void MachineGauge(string name, Func<double> gauge)
        {
            GetDefault().AddGauge(Environment.MachineName + "." + name, new Gauge(gauge));
        }

        public static void Gauge(string name, Func<double> gauge)
        {
            GetDefault().AddGauge(name, new Gauge(gauge));
        }

        public static void RemoveGauge(string name)
        {
            GetDefault().DeleteGauge(name);
        }

        public static void AddMetric(string name, int n)
        {
            GetDefault().RecordMetric(name, n);
        }

        public static void Time(string name, int millis)
        {
            GetDefault().RecordMetric(name, millis);
        }

        public static void Time(string name, Stopwatch timer)
        {
            GetDefault().RecordMetric(name, timer);
        }

        public static void Time(string tag, Action action)
        {
            GetDefault().RecordMetric(tag, action);
        }

        public static T Time<T>(string tag, Func<T> func)
        {
            return GetDefault().RecordMetric(tag, func);
        }

        public static Metric RemoveTime(string tag)
        {
            return GetDefault().DeleteTime(tag);
        }

        public static long Incr(string name, int count)
        {
            return GetDefault().Increment(name, count);
        }

        public static long Incr(string name)
        {
            return GetDefault().Increment(name);
        }

        public static AtomicLong RemoveCounter(string name)
        {
            return GetDefault().DeleteCounter(name);
        }

        public static StatsCollection GetDefault()
        {
            return NamedCollections[string.Empty];
        }

        public static AtomicLong Delta(AtomicLong oldValue, AtomicLong newValue)
        {
            if (oldValue.Value <= newValue.Value)
            {
                return new AtomicLong(newValue.Value - oldValue.Value);
            }

            var count = (AtomicLong.MaxValue.Value - oldValue.Value) + (newValue.Value - AtomicLong.MinValue.Value);
            return new AtomicLong(count + 1);
        }

        public static void WriteJson(JsonWriter jsonWriter)
        {
            var stats = GetDefault();

            jsonWriter.WriteStartObject();
            jsonWriter.WritePropertyName("metrics");
            jsonWriter.WriteStartObject();
            foreach (var metric in stats.Metrics)
            {
                jsonWriter.WritePropertyName(metric.Key.ToLower());
                metric.Value.WriteJson(jsonWriter);
            }

            jsonWriter.WriteEndObject();
            jsonWriter.WritePropertyName("counters");
            jsonWriter.WriteStartObject();
            foreach (var counter in stats.Counters)
            {
                jsonWriter.WritePropertyName(counter.Key.ToLower());
                jsonWriter.WriteValue(counter.Value.Value);
            }

            jsonWriter.WriteEndObject();
            jsonWriter.WritePropertyName("gauges");
            jsonWriter.WriteStartObject();
            foreach (var gauge in stats.Gauges)
            {
                jsonWriter.WritePropertyName(gauge.Key.ToLower());
                jsonWriter.WriteValue(gauge.Value.Value);
            }

            jsonWriter.WriteEndObject();
        }

        public static IDictionary<string, object> ToDictionary()
        {
            var stats = GetDefault();
            return new SortedDictionary<string, object>
            {
              { "counters", BuildDict(stats.Counters, c => c.Value) },
              { "metrics", BuildDict(stats.Metrics, m => m.ToDictionary()) },
              { "gauges", BuildDict(stats.Gauges, g => g.Value) }
            };
        }

        private static SortedDictionary<string, object> BuildDict<TRender, TValue>(IEnumerable<KeyValuePair<string, TValue>> origin, Func<TValue, TRender> display)
        {
            var destination = new SortedDictionary<string, object>();
            origin.Each(kv => destination[kv.Key] = display(kv.Value));
            return destination;
        }
    }
}


text:
package com.globusltd.recyclerview;

import android.support.annotation.MainThread;

import com.globusltd.recyclerview.datasource.Datasource;

/**
 * Interface describes component that supports replacing internal {@link Datasource}
 * without interruption to the system.
 *
 * @param <E> Type of elements handled by datasource.
 */
@MainThread
public interface DatasourceSwappable<E> extends Swappable<Datasource<? extends E>> {
}


text:
require 'spec_helper'
feature 'Accounts' do
	scenario 'creating an account' do
		visit registration.root_path
		click_link 'Account Sign Up'
		fill_in 'Name', :with  => 'Test'
		fill_in 'Email', :with => 'test@example.com'
		password_field_id = 'account_owner_attributes_password'
		fill_in	password_field_id, :with => 'password'
		fill_in 'Password confirmation', :with => 'password'
		click_button 'Create Account'
		success_message = 'Your account has been successfully created.'
		page.should have_content success_message
	end

end


text:
package org.camunda.bpm.engine.rest.hal.user;

import org.camunda.bpm.engine.identity.User;
import org.camunda.bpm.engine.rest.UserRestService;
import org.camunda.bpm.engine.rest.hal.HalIdResource;
import org.camunda.bpm.engine.rest.hal.HalRelation;
import org.camunda.bpm.engine.rest.hal.HalResource;

import javax.ws.rs.core.UriBuilder;

/**
 * @author Daniel Meyer
 *
 */
public class HalUser extends HalResource<HalUser> implements HalIdResource {

  public final static HalRelation REL_SELF =
    HalRelation.build("self", UserRestService.class, UriBuilder.fromPath(UserRestService.PATH).path("{id}"));

  protected String id;
  protected String firstName;
  protected String lastName;
  protected String email;

  public static HalUser fromUser(User user) {

    HalUser halUser = new HalUser();

    halUser.id = user.getId();
    halUser.firstName = user.getFirstName();
    halUser.lastName = user.getLastName();
    halUser.email = user.getEmail();

    halUser.linker.createLink(REL_SELF, user.getId());

    return halUser;

  }

  public String getId() {
    return id;
  }

  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public String getEmail() {
    return email;
  }

}


text:
require_relative '../spec_helper'

module Drift
  describe BlogPost do
    before :each do
      @datetime = Time.local(2013, 05, 14, 14, 20, 30)
      @slug = 'test-blog-post'
      @file = "#{@datetime.strftime('%Y')}-#{@datetime.strftime('%m')}-#{@datetime.strftime('%d')}_#{@datetime.hour}#{@datetime.min}#{@datetime.sec}_#{@slug}.textile"
      @blog_post = BlogPost.new(:file => @file)
    end

    it "should have a default source" do
      BlogPost.source.length.should be > 0
    end

    it "should have a default markup_ext" do
      BlogPost.markup_ext.length.should be > 0
    end

    it "should parse datetime from filename" do
      BlogPost.parse_datetime_from_filename(@file).should eq @datetime
    end

    it "should parse slug from filename" do
      BlogPost.parse_slug_from_filename(@file).should eq @slug
    end

    it "should derive created_at from filename" do
      @blog_post.created_at.should eq @datetime
    end

    it "should derive slug from filename" do
      @blog_post.slug.should eq @slug
    end
  end
end


text:
import boto3
import pytest
import sure  # noqa # pylint: disable=unused-import
from moto import mock_s3
from moto import settings
from unittest import SkipTest

@pytest.fixture(scope="function", name="aws_credentials")
def fixture_aws_credentials(monkeypatch):
    if settings.TEST_SERVER_MODE:
        raise SkipTest("No point in testing this in ServerMode.")
    """Mocked AWS Credentials for moto."""
    monkeypatch.setenv("AWS_ACCESS_KEY_ID", "testing")
    monkeypatch.setenv("AWS_SECRET_ACCESS_KEY", "testing")
    monkeypatch.setenv("AWS_SECURITY_TOKEN", "testing")
    monkeypatch.setenv("AWS_SESSION_TOKEN", "testing")

def test_mock_works_with_client_created_inside(
    aws_credentials,
):  # pylint: disable=unused-argument
    m = mock_s3()
    m.start()
    client = boto3.client("s3", region_name="us-east-1")

    b = client.list_buckets()
    b["Buckets"].should.equal([])
    m.stop()

def test_mock_works_with_client_created_outside(
    aws_credentials,
):  # pylint: disable=unused-argument
    # Create the boto3 client first
    outside_client = boto3.client("s3", region_name="us-east-1")

    # Start the mock afterwards - which does not mock an already created client
    m = mock_s3()
    m.start()

    # So remind us to mock this client
    from moto.core import patch_client

    patch_client(outside_client)

    b = outside_client.list_buckets()
    b["Buckets"].should.equal([])
    m.stop()

def test_mock_works_with_resource_created_outside(
    aws_credentials,
):  # pylint: disable=unused-argument
    # Create the boto3 client first
    outside_resource = boto3.resource("s3", region_name="us-east-1")

    # Start the mock afterwards - which does not mock an already created resource
    m = mock_s3()
    m.start()

    # So remind us to mock this client
    from moto.core import patch_resource

    patch_resource(outside_resource)

    b = list(outside_resource.buckets.all())
    b.should.equal([])
    m.stop()

def test_patch_client_does_not_work_for_random_parameters():
    from moto.core import patch_client

    with pytest.raises(Exception, match="Argument sth should be of type boto3.client"):
        patch_client("sth")

def test_patch_resource_does_not_work_for_random_parameters():
    from moto.core import patch_resource

    with pytest.raises(
        Exception, match="Argument sth should be of type boto3.resource"
    ):
        patch_resource("sth")

class ImportantBusinessLogic:
    def __init__(self):
        self._s3 = boto3.client("s3", region_name="us-east-1")

    def do_important_things(self):
        return self._s3.list_buckets()["Buckets"]

def test_mock_works_when_replacing_client(
    aws_credentials,
):  # pylint: disable=unused-argument

    logic = ImportantBusinessLogic()

    m = mock_s3()
    m.start()

    # This will fail, as the S3 client was created before the mock was initialized
    try:
        logic.do_important_things()
    except Exception as e:
        str(e).should.contain("InvalidAccessKeyId")

    client_initialized_after_mock = boto3.client("s3", region_name="us-east-1")
    logic._s3 = client_initialized_after_mock
    # This will work, as we now use a properly mocked client
    logic.do_important_things().should.equal([])

    m.stop()


text:
<?php

/**
 * @file
 * Contains \Drupal\Tests\Core\Extension\ThemeHandlerTest.
 */

namespace Drupal\Tests\Core\Extension;

use Drupal\Core\Cache\MemoryBackend;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\InfoParser;
use Drupal\Core\Extension\ThemeHandler;
use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
use Drupal\Core\Lock\NullLockBackend;
use Drupal\Core\State\State;
use Drupal\Tests\UnitTestCase;

/**
 * @coversDefaultClass \Drupal\Core\Extension\ThemeHandler
 * @group Extension
 */
class ThemeHandlerTest extends UnitTestCase {

  /**
   * The mocked info parser.
   *
   * @var \Drupal\Core\Extension\InfoParserInterface|\PHPUnit_Framework_MockObject_MockObject
   */
  protected $infoParser;

  /**
   * The mocked state backend.
   *
   * @var \Drupal\Core\State\StateInterface|\PHPUnit_Framework_MockObject_MockObject
   */
  protected $state;

  /**
   * The mocked config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
   */
  protected $configFactory;

  /**
   * The mocked module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
   */
  protected $moduleHandler;

  /**
   * The extension discovery.
   *
   * @var \Drupal\Core\Extension\ExtensionDiscovery|\PHPUnit_Framework_MockObject_MockObject
   */
  protected $extensionDiscovery;

  /**
   * The tested theme handler.
   *
   * @var \Drupal\Core\Extension\ThemeHandler|\Drupal\Tests\Core\Extension\StubThemeHandler
   */
  protected $themeHandler;

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();

    $this->configFactory = $this->getConfigFactoryStub([
      'core.extension' => [
        'module' => [],
        'theme' => [],
        'disabled' => [
          'theme' => [],
        ],
      ],
    ]);
    $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
    $this->state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend());
    $this->infoParser = $this->getMock('Drupal\Core\Extension\InfoParserInterface');
    $this->extensionDiscovery = $this->getMockBuilder('Drupal\Core\Extension\ExtensionDiscovery')
      ->disableOriginalConstructor()
      ->getMock();
    $this->themeHandler = new StubThemeHandler($this->root, $this->configFactory, $this->moduleHandler, $this->state, $this->infoParser, $this->extensionDiscovery);

    $cache_tags_invalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
    $this->getContainerWithCacheTagsInvalidator($cache_tags_invalidator);
  }

  /**
   * Tests rebuilding the theme data.
   *
   * @see \Drupal\Core\Extension\ThemeHandler::rebuildThemeData()
   */
  public function testRebuildThemeData() {
    $this->extensionDiscovery->expects($this->at(0))
      ->method('scan')
      ->with('theme')
      ->will($this->returnValue([
        'seven' => new Extension($this->root, 'theme', $this->root . '/core/themes/seven/seven.info.yml', 'seven.theme'),
      ]));
    $this->extensionDiscovery->expects($this->at(1))
      ->method('scan')
      ->with('theme_engine')
      ->will($this->returnValue([
        'twig' => new Extension($this->root, 'theme_engine', $this->root . '/core/themes/engines/twig/twig.info.yml', 'twig.engine'),
      ]));
    $this->infoParser->expects($this->once())
      ->method('parse')
      ->with($this->root . '/core/themes/seven/seven.info.yml')
      ->will($this->returnCallback(function ($file) {
        $info_parser = new InfoParser();
        return $info_parser->parse($file);
      }));
    $this->moduleHandler->expects($this->once())
      ->method('buildModuleDependencies')
      ->will($this->returnArgument(0));

    $this->moduleHandler->expects($this->once())
      ->method('alter');

    $theme_data = $this->themeHandler->rebuildThemeData();
    $this->assertCount(1, $theme_data);
    $info = $theme_data['seven'];

    // Ensure some basic properties.
    $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info);
    $this->assertEquals('seven', $info->getName());
    $this->assertEquals($this->root . '/core/themes/seven/seven.info.yml', $info->getPathname());
    $this->assertEquals($this->root . '/core/themes/seven/seven.theme', $info->getExtensionPathname());
    $this->assertEquals($this->root . '/core/themes/engines/twig/twig.engine', $info->owner);
    $this->assertEquals('twig', $info->prefix);

    $this->assertEquals('twig', $info->info['engine']);
    $this->assertEquals(['seven/global-styling'], $info->info['libraries']);
  }

  /**
   * Tests empty libraries in theme.info.yml file.
   */
  public function testThemeLibrariesEmpty() {
    $theme = new Extension($this->root, 'theme', '/core/modules/system/tests/themes/test_theme_libraries_empty', 'test_theme_libraries_empty.info.yml');
    try {
      $this->themeHandler->addTheme($theme);
      $this->assertTrue(TRUE, 'Empty libraries key in theme.info.yml does not cause PHP warning');
    }
    catch (\Exception $e) {
      $this->fail('Empty libraries key in theme.info.yml causes PHP warning.');
    }
  }

  /**
   * Tests rebuild the theme data with theme parents.
   */
  public function testRebuildThemeDataWithThemeParents() {
    $this->extensionDiscovery->expects($this->at(0))
      ->method('scan')
      ->with('theme')
      ->will($this->returnValue([
        'test_subtheme' => new Extension($this->root, 'theme', $this->root . '/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml', 'test_subtheme.info.yml'),
        'test_basetheme' => new Extension($this->root, 'theme', $this->root . '/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml', 'test_basetheme.info.yml'),
      ]));
    $this->extensionDiscovery->expects($this->at(1))
      ->method('scan')
      ->with('theme_engine')
      ->will($this->returnValue([
        'twig' => new Extension($this->root, 'theme_engine', $this->root . '/core/themes/engines/twig/twig.info.yml', 'twig.engine'),
      ]));
    $this->infoParser->expects($this->at(0))
      ->method('parse')
      ->with($this->root . '/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml')
      ->will($this->returnCallback(function ($file) {
        $info_parser = new InfoParser();
        return $info_parser->parse($file);
      }));
    $this->infoParser->expects($this->at(1))
      ->method('parse')
      ->with($this->root . '/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml')
      ->will($this->returnCallback(function ($file) {
        $info_parser = new InfoParser();
        return $info_parser->parse($file);
      }));
    $this->moduleHandler->expects($this->once())
      ->method('buildModuleDependencies')
      ->will($this->returnArgument(0));

    $theme_data = $this->themeHandler->rebuildThemeData();
    $this->assertCount(2, $theme_data);

    $info_basetheme = $theme_data['test_basetheme'];
    $info_subtheme = $theme_data['test_subtheme'];

    // Ensure some basic properties.
    $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info_basetheme);
    $this->assertEquals('test_basetheme', $info_basetheme->getName());
    $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info_subtheme);
    $this->assertEquals('test_subtheme', $info_subtheme->getName());

    // Test the parent/child-theme properties.
    $info_subtheme->info['base theme'] = 'test_basetheme';
    $info_basetheme->sub_themes = ['test_subtheme'];

    $this->assertEquals($this->root . '/core/themes/engines/twig/twig.engine', $info_basetheme->owner);
    $this->assertEquals('twig', $info_basetheme->prefix);
    $this->assertEquals($this->root . '/core/themes/engines/twig/twig.engine', $info_subtheme->owner);
    $this->assertEquals('twig', $info_subtheme->prefix);
  }

  /**
   * Tests getting the base themes for a set a defines themes.
   *
   * @param array $themes
   *   An array of available themes, keyed by the theme name.
   * @param string $theme
   *   The theme name to find all its base themes.
   * @param array $expected
   *   The expected base themes.
   *
   * @dataProvider providerTestGetBaseThemes
   */
  public function testGetBaseThemes(array $themes, $theme, array $expected) {
    $base_themes = $this->themeHandler->getBaseThemes($themes, $theme);
    $this->assertEquals($expected, $base_themes);
  }

  /**
   * Provides test data for testGetBaseThemes.
   *
   * @return array
   *   An array of theme test data.
   */
  public function providerTestGetBaseThemes() {
    $data = [];

    // Tests a theme without any base theme.
    $themes = [];
    $themes['test_1'] = (object) [
      'name' => 'test_1',
      'info' => [
        'name' => 'test_1',
      ],
    ];
    $data[] = [$themes, 'test_1', []];

    // Tests a theme with a non existing base theme.
    $themes = [];
    $themes['test_1'] = (object) [
      'name' => 'test_1',
      'info' => [
        'name' => 'test_1',
        'base theme' => 'test_2',
      ],
    ];
    $data[] = [$themes, 'test_1', ['test_2' => NULL]];

    // Tests a theme with a single existing base theme.
    $themes = [];
    $themes['test_1'] = (object) [
      'name' => 'test_1',
      'info' => [
        'name' => 'test_1',
        'base theme' => 'test_2',
      ],
    ];
    $themes['test_2'] = (object) [
      'name' => 'test_2',
      'info' => [
        'name' => 'test_2',
      ],
    ];
    $data[] = [$themes, 'test_1', ['test_2' => 'test_2']];

    // Tests a theme with multiple base themes.
    $themes = [];
    $themes['test_1'] = (object) [
      'name' => 'test_1',
      'info' => [
        'name' => 'test_1',
        'base theme' => 'test_2',
      ],
    ];
    $themes['test_2'] = (object) [
      'name' => 'test_2',
      'info' => [
        'name' => 'test_2',
        'base theme' => 'test_3',
      ],
    ];
    $themes['test_3'] = (object) [
      'name' => 'test_3',
      'info' => [
        'name' => 'test_3',
      ],
    ];
    $data[] = [
      $themes,
      'test_1',
      ['test_2' => 'test_2', 'test_3' => 'test_3'],
    ];

    return $data;
  }

}

/**
 * Extends the default theme handler to mock some drupal_ methods.
 */
class StubThemeHandler extends ThemeHandler {

  /**
   * Whether the CSS cache was cleared.
   *
   * @var bool
   */
  protected $clearedCssCache;

  /**
   * Whether the registry should be rebuilt.
   *
   * @var bool
   */
  protected $registryRebuild;

  /**
   * A list of themes keyed by name.
   *
   * @var array
   */
  protected $systemList;

  /**
   * {@inheritdoc}
   */
  protected function clearCssCache() {
    $this->clearedCssCache = TRUE;
  }

  /**
   * {@inheritdoc}
   */
  protected function themeRegistryRebuild() {
    $this->registryRebuild = TRUE;
  }

  /**
   * {@inheritdoc}
   */
  protected function systemThemeList() {
    return $this->systemList;
  }

  /**
   * {@inheritdoc}
   */
  protected function systemListReset() {
  }

}

if (!defined('DRUPAL_EXTENSION_NAME_MAX_LENGTH')) {
  define('DRUPAL_EXTENSION_NAME_MAX_LENGTH', 50);
}
if (!defined('DRUPAL_PHP_FUNCTION_PATTERN')) {
  define('DRUPAL_PHP_FUNCTION_PATTERN', '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*');
}
if (!defined('DRUPAL_MINIMUM_PHP')) {
  define('DRUPAL_MINIMUM_PHP', '5.3.10');
}


text:
		<li class="<?php if($this->uri->segment(2)=="listarLocalizacao"){echo "active";}?>">
            <a href="<?php echo base_url('localizacao/listarLocalizacao')?>">Ativos por Localização

        <li class="<?php if($this->uri->segment(2)=="listarLocalizacao"){echo "active";}?>">
            <a href="<?php echo base_url('localizacao/listarLocalizacao')?>">Rastreabilidade

        <li class="<?php if($this->uri->segment(2)==""){echo "active";}?>">
            <a href="<?php echo base_url('localizacao/listarLocalizacao')?>">Divergência


text:
layout:     post
title:      Javaswag выпуск 25
date:       2017-01-31
summary: 	Это первый выпуск в этом году! Выпуск немного припозднился, но дальше по расписанию. Поехали! В выпуске "оживляем" Skip List, разбираемся с размеров пула соединений и смотрим видео про улучшение производительности строк в Java 9.
categories: javaswag
---

Привет!
Это первый выпуск в этом году! Выпуск немного припозднился, но дальше по расписанию. Поехали!
В выпуске "оживляем" Skip List, разбираемся с размеров пула соединений и смотрим видео про улучшение производительности строк в Java 9.

[http://bruceeckel.github.io/2017/01/13/constructors-are-not-thread-safe/](http://bruceeckel.github.io/2017/01/13/constructors-are-not-thread-safe/)

**Constructors Are Not Thread-Safe**

Брюс Эккель рассуждает про потоко-небезопасные конструкторы в Java. На примерах показывает к чему это может привести, и как сделать создание объекта потокобезопасным.

[http://thenewstack.io/three-stages-software-engineering-scale/](http://thenewstack.io/three-stages-software-engineering-scale/)

**The Three Stages of Software Engineering**

Три этапа развития целей проекта - простота, эффективность, организационная структура. Такие приоритеты должны быть у компании по мнению разработчика из Линкадина.
Если бы можно было вынести всего одно предложение из всей статьи, то это было бы "Пока ваша команда меньше 30 человек основным приоритетом должна быть простота".

[http://code.flickr.net/2017/01/05/a-year-without-a-byte/](http://code.flickr.net/2017/01/05/a-year-without-a-byte/)

**A Year Without a Byte**

Сервис flick в 2016 году ставил цель сократить расходы на хранение фотографий. Весьма амбициозная задача для фотохостинга, учитывая растущее каждый год количество загружаемого контента! Фликровцы рассказывают как пережали уже существующие фотографии, уменьшили количество резервной памяти на дисках и размеры маленьких версий фоток.

[http://ticki.github.io/blog/skip-lists-done-right/](http://ticki.github.io/blog/skip-lists-done-right/)

**Skip Lists: Done Right**

Список с пропусками, он же Skip Lists - несправедливо "забытая" структура данных в джаве. Статья поможет освежить в памяти его устройство, и напомнит случаи, когда "скип лист" будет полезен.

[https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing)

**About Pool Sizing**
Какой должен быть размер пула подключения к базе данных? 10000? 1000? 100?

Если вы хоть раз задумывались над размером пула соединений к базе данных, то эта статья для вас.

[https://youtu.be/_evzaAkd594](https://youtu.be/_evzaAkd594)

**Aleksey Shipilev - String Enhancements in JDK 9**

За 20 минут Алексей Шипилев расскажет про улучшения производительности части строк в грядущей Java 9. Маст си для джава девелопера.

[https://medium.com/@lukleDev/how-effective-java-may-have-influenced-the-design-of-kotlin-part-1-45fd64c2f974#.qzpd6ebwm](https://medium.com/@lukleDev/how-effective-java-may-have-influenced-the-design-of-kotlin-part-1-45fd64c2f974#.qzpd6ebwm)

**How "Effective Java" may have influenced the design of Kotlin — Part 1**

Немного Котлина. А именно то,какие улучшения язык Котлин впитал из Джавы.

[http://www.baeldung.com/lmax-disruptor-concurrency](http://www.baeldung.com/lmax-disruptor-concurrency)

**Concurrency with LMAX Disruptor – An Introduction**
В блоге баелдунга рассказывается о том, как устроен фреймворк дизраптор и как ему удается быть настолько быстрым. Все дело в "mechanical sympathy" — процессе когда программа работает "в унисон" с железками.


text:
<?php declare(strict_types=1);
namespace ImboClient\Response;

use DateTime;
use ImboClient\Utils;
use Psr\Http\Message\ResponseInterface;

class User extends ApiResponse
{
    private string $user;
    private int $numImages;
    private DateTime $lastModified;

    public function __construct(string $user, int $numImages, DateTime $lastModified)
    {
        $this->user = $user;
        $this->numImages = $numImages;
        $this->lastModified = $lastModified;
    }

    public static function fromHttpResponse(ResponseInterface $response): self
    {
        /** @var array{user:string,numImages:int,lastModified:string} */
        $body = Utils::convertResponseToArray($response);
        return (new self($body['user'], $body['numImages'], new DateTime($body['lastModified'])))->withResponse($response);
    }

    public function getUser(): string
    {
        return $this->user;
    }

    public function getNumImages(): int
    {
        return $this->numImages;
    }

    public function getLastModified(): DateTime
    {
        return $this->lastModified;
    }

    protected function getArrayOffsets(): array
    {
        return [
            'user' => fn (): string => $this->getUser(),
            'numImages' => fn (): int => $this->getNumImages(),
            'lastModified' => fn (): DateTime => $this->getLastModified(),
        ];
    }
}


text:
require 'spec_helper'

describe TrelloCli::Requests::CreateCard do
  before do
    Trello.should_receive(:configure)
  end

  let(:members_mock) { double "members" }
  let(:trello_card_mock) { double 'trello card' }
  let(:member_struct) { Struct.new(:attributes) }

  before do
    @args = { :name      => 'name',
              :desc      => 'desc',
              :board_id  => '123',
              :list_id   => '321',
              :members   => ["user1", "user2"] }
    @options = { 'name'      => @args[:name],
                 'desc'      => @args[:desc],
                 'idBoard'   => @args[:board_id],
                 'idList'    => @args[:list_id],
                 'idMembers' => "id1,id2" }
  end

  it "should create the requested card" do
    TrelloCli::Requests::Members.should_receive(:new).
                                 with("123").
                                 and_return members_mock
    @args[:members].each do |m|
      members_mock.should_receive(:member_exists_in_board?).with(m).and_return true
    end
    members_mock.should_receive(:find_member_by_username_in_board).
                 with("user1").and_return member_struct.new(id: "id1")
    members_mock.should_receive(:find_member_by_username_in_board).
                 with("user2").and_return member_struct.new(id: "id2")

    Trello::Card.should_receive(:new).
                 with(@options).
                 and_return trello_card_mock
    trello_card_mock.should_receive(:save)
    subject.create @args
  end
end


text:
"""Tests for certbot._internal.plugins.null."""
import unittest

try:
    import mock
except ImportError: # pragma: no cover
    from unittest import mock

class InstallerTest(unittest.TestCase):
    """Tests for certbot._internal.plugins.null.Installer."""

    def setUp(self):
        from certbot._internal.plugins.null import Installer
        self.installer = Installer(config=mock.MagicMock(), name="null")

    def test_it(self):
        self.assertIsInstance(self.installer.more_info(), str)
        self.assertEqual([], self.installer.get_all_names())
        self.assertEqual([], self.installer.supported_enhancements())

if __name__ == "__main__":
    unittest.main()  # pragma: no cover


text:
% use Accuracy = mean( distanceDifference:LIST )
% use Precision = SD( distanceDiffence:LIST )
%===============================================================================
% Ignore this:
% Accuracy
%   = (TruePositive + TrueNegative) / (Postives + Negatives)
%
% Precision
%   = (TruePositive) / (TruePositive + FalsePositive)
%===============================================================================
% 1. Get (centerX, centerY) for original image
% 2. Get (centerX, centerY) for synthetic image
% 3. (Calculate difference and count?)
% 4. Calculate mean and SD for both
%===============================================================================
clear all, close all, clc

%imagePath = '2\images\001_a5_002_t001.tif';    % Path format in Windows
imagePath = '2/images/001_a5_002_t001.tif';     % Path format in OSX/Linux
masksize = 5;

I = imread(imagePath);
I = double(I);

%===============================================================================
% Get X, Y coordinates for original and synthetic images
%===============================================================================
[originalImgCoord_X, originalImgCoord_Y] = accuracyofsubpixel(I);

syntheticImg = generatesyntheticimg(I, masksize, imagePath);
[syntheticImgCoord_X, syntheticImgCoord_Y] = accuracyofsubpixel(syntheticImg);

%===============================================================================
% count
%===============================================================================
size_original = size(originalImgCoord_X);
size_synthetic = size(syntheticImgCoord_X);
count_original = size_original(2);
count_synthetic = size_synthetic(2);

countDifference =  count_original - count_synthetic;

%===============================================================================
% Turn X,Y vectors to coordinate system; (X, Y)
%===============================================================================
originalImgCoord = [];
for i=1:count_original
    originalImgCoord = [originalImgCoord ; [originalImgCoord_X(i), originalImgCoord_Y(i)] ];
end

syntheticImgCoord = [];
for i=1:count_synthetic
    syntheticImgCoord = [syntheticImgCoord ; [syntheticImgCoord_X(i), syntheticImgCoord_Y(i)] ];
end

%===============================================================================
% Calculate mean and SD
%===============================================================================
originalMean = mean(originalImgCoord);
originalSD = std(originalImgCoord);
syntheticMean = mean(syntheticImgCoord);
syntheticSD = std(syntheticImgCoord);

fprintf('Original image mean coordinates are:\n (%f, %f)\n', originalMean(1), originalMean(2) )
fprintf('The standard deviation of the coordinates are:\n (%f, %f)\n', originalSD(1), originalSD(2) )

fprintf('Synthetic image mean coordinates are:\n (%f, %f)\n', syntheticMean(1), syntheticMean(2) )
fprintf('The standard deviation of the coordinates are:\n (%f, %f)\n', syntheticSD(1), syntheticSD(2) )

% Calculate accuracy and precision
accuracy = (originalMean - syntheticMean) ./ syntheticMean * 100;    % in percentage
precision = (originalSD - syntheticSD) ./ syntheticSD * 100;         % in percentage
fprintf('\n')
fprintf('The accuracy of the original image from ground truth is:\n (%f%%, %f%%)\n', accuracy(1), accuracy(2) )
fprintf('The precision of the original image from ground truth is:\n (%f%%, %f%%)\n', precision(1), precision(2) )

%===============================================================================
% Ignore: Following is not needed
% Nearest-neighbor to get distance difference between originalImg vs. syntheticImg
%   1. for each center in originalImg (has less centers), find nearest center in syntheticImg (has more centers) (output: list)
%   2. calculate the distance (input: list; output: list)
%   3. calculate mean and SD of the distances (input: list; output: [mean, SD]
%===============================================================================
% check tutorial on how to do:
%   http://www.mathworks.com/help/stats/knnsearch.html
%   TO DO: figure out how to use n and d, or need to use another algo instead
%[n,d]=knnsearch(originalImgCoord, syntheticImgCoord, 'k',10, 'distance','minkowski', 'p',5);


text:
title: Sarah Grayson
summary: Voice actor (Gone Home)
date: 2015-09-29
categories:
- actor
- game
- mac
- voice
---

### Who are you, and what do you do?

I'm [Sarah Grayson](http://sarahgrayson.com/ "Sarah's website.") and I'm a voice actor. Ever since I was a little kid watching Saturday morning cartoons, I'd dreamt about being a part of this amazing world of voiceover. It wasn't until a chance meeting with a voiceover coach in 2008 that it suddenly began turning into a reality. Six fantastic years later and I've had the pleasure of lending my voice to commercials, non-broadcast works, and video games.

The most recently published game was [Gone Home][gone-home] by The Fullbright Company, in which I play the protagonist's younger sister, Sam.

### What hardware do you use?

My primary microphone is an [MXL 990 condenser mic][mxl-990] with a shock mount and pop filter. The mic is run through a [DigiDesign Mbox 2 Mini][mbox-2-mini] and into a well-loved [MacBook][]. I also have a [Blue Yeti USB mic][yeti] that I use with this great little portable sound booth when I'm away from home.

Of course, when a gig requires a visit to a professional studio, there is much more fun and fancy hardware involved.

### And what software?

My MacBook is running [OS X][macos]. Beyond that, I'm afraid that answering this truthfully is going to highlight an embarrassing wonkiness in my process. I record with [GarageBand][], but I edit with [Peak LE][peak-le]. Ideally, I'd be doing everything through one program, and initially did with Peak, but it developed a nasty bug along the way and everything I record through it now sounds like I'm talking at half speed under water. That's when I turned to GarageBand for the recording side, but I still edit in Peak since that's where I'm most proficient. It's an odd system, but it'll work until I get things sorted.

### What would be your dream setup?

That's a really tough question to answer. I would of course love to put together a top-of-the-line home studio. I think back to the studios I've recorded in over the years and it would be a dream to model my setup after any one of them. If I had unlimited funds, I'd probably just call up an audio engineer friend of mine and tell him to pull out all the stops.

After posing this hypothetical to him, it sounds like I'd start with a [Neve 1073 console][1073-console-module], [Manley VoxBox Compressor][voxbox], and [Manley Massive Passive EQ][massive-passive]... and some fun acoustic foam soundproofing, of course. I love that stuff. I'd also upgrade my laptop and its software for when I record on the road.

[1073-console-module]: https://en.wikipedia.org/wiki/Neve_Electronics#Neve_1073_Console_Module "A preamp."
[garageband]: https://www.apple.com/mac/garageband/ "An audio recording and editing tool for the Mac."
[gone-home]: https://gonehome.game/ "A story exploration video game."
[macbook]: https://en.wikipedia.org/wiki/MacBook "A laptop."
[macos]: https://en.wikipedia.org/wiki/MacOS "An operating system for Mac hardware."
[massive-passive]: https://www.manley.com/products/view/msmp "A two channel equaliser."
[mbox-2-mini]: https://www.amazon.com/Digidesign-Portable-USB-Powered-Tools-Workstation/dp/B000KW4TZK/ "A USB-powered audio/MIDI production system."
[mxl-990]: http://www.mxlmics.com/microphones/900-series/990/ "A condenser microphone."
[peak-le]: https://www.macupdate.com/app/mac/9784/bias-peak-le "A music creation and editing tool."
[voxbox]: https://www.manley.com/products/view/mvbx "A preamp and equaliser."
[yeti]: http://bluemic.com/yeti/ "A USB microphone."


text:
title: Skill Practice

source:
- title: Common Core Basics
  subject: Social Studies
  chapter: 1
  toc_type: Lesson Review
  toc_number: 1.1
  pages: 18 - 25

questions:
  - excerpt: 1 - 3
    text: >
      The English Bill of Rights
The 1600s were a time of conflict between the British king, the English people, and Parliament (the British legislature). The conflict ended in 1689 when new monarchs, William III and Mary, accepted the English Bill of Rights. This document helped create a constitutional monarchy. The English Bill of Rights stated that the monarch served at the will of Parliament. The Bill of Rights strengthened the rights of common people; For example, people could no longer be taxed simply because the king wanted money. Laws could not be changed without Parliament's approval. Members of Parliament were to be freely elected. The Bill of Rights guaranteed a just and fair government that answered to the people.

      The US Bill of Rights
To protect the rights of Americans, the US Congress approved the Bill of Rights in 1789. Among the rights protected are the following:

Amendment 1: People have the right to practice any religion they choose.

Amendment 4: People and their homes cannot be searched without probable cause.

Amendment 8: Persons arrested cannot be punished in cruel or unusual ways.

Amendment 9: The rights of the people are not limited to the rights listed in the Constitution.

  - number: 1
    text: >
      Why do you think the authors of the US Bill of Rights thought it was necessary to include these rights in the Constitution?
    choice:
      - option: blank
    answer:
      - text: >
          The founders knew that some rights had been abused in the past. They wanted to protect citizens in the new country.
  - number: 2
    text: >
      In what way did the English Bill of Rights influence the US Bill of Rights?
    choice:
      - option: blank
    answer:
      - text: >
          The authors of the Constitution and the Bill of Rights were descended from English people, so English law would have influenced their thinking. They knew that the English Bill of Rights had protected the people from the king, and they thought all people should have those same rights.
  - number: 3
    text: >
      Why do you think the authors of the US Bill of Rights included Amendment 9?
    choice:
      - option: blank
    answer:
      - text: >
          The authors knew they couldn't name every right, but they wanted to protect citizens from all possible abuses by the government.

layout: cc_review
---


text:
<!DOCTYPE html>

    <meta charset="utf-8" />
    <title>TODO List</title>

Presenting functionality of the TODO list module