3
__author__ = 'David Malcolm <dmalcolm@redhat.com>'
7
# Takes an image file, uses Imagemagick to chop it into tiles,
8
# then arranges the Nautilus thumbnail icons into a collage
9
# FIXME: somewhat unstable, requires a 640x480 image called victim.png
11
from dogtail.apps.wrappers.nautilus import *
12
from math import sin, cos, pi
17
#dogtail.config.config.debugSearching=True
18
#dogtail.config.config.debugSleep = True
23
def __init__(self, sourceImage):
24
self.sourceImage = os.path.abspath(sourceImage)
25
self.basePath = os.curdir
26
self.piecesPath = os.path.abspath(os.path.join(self.basePath, "JigsawPieces"))
27
self.resultPath = os.path.abspath(os.path.join(self.basePath, "JigsawResult"))
28
self.pieceArg = os.path.join(self.piecesPath, "piece.png")
33
self.pieceWidth = self.baseWidth/self.divisor
34
self.pieceHeight = self.baseHeight/self.divisor
35
self.iconWidth = 70.0 # self.baseWidth/self.divisor
36
self.iconHeight = 54.0 # self.baseHeight/self.divisor
38
def makeCropCommand(self):
39
return 'convert -crop %sx%s %s %s'%(self.pieceWidth, self.pieceHeight, self.sourceImage, self.pieceArg)
41
def targetLocation(self, baseXY, index):
42
(baseX, baseY) = baseXY
43
(pieceX,pieceY) = ((float(index)%self.divisor)*self.iconWidth, (float(index)/self.divisor)*self.iconHeight)
44
return (baseX+pieceX,baseY+pieceY)
46
def makeDirectories(self):
47
try: os.mkdir(self.piecesPath)
50
try: os.mkdir(self.resultPath)
54
def __init__(self, startXY, endXY):
55
self.startXY = startXY
58
def doDrag(self, duration, steps):
59
ev = atspi.EventGenerator()
61
(x,y) = self.calcCoord(0.0)
62
ev.absoluteMotion(x, y)
66
for step in range(steps):
67
frac = float(step)/float(steps)
68
(x,y) = self.calcCoord(frac)
69
#doDelay(duration/steps)
70
ev.absoluteMotion(x, y)
72
(x,y) = self.calcCoord(1.0)
73
ev.absoluteMotion(x,y)
77
def calcCoord(self, frac):
78
raise NotImplementedError
80
class LinearDrag(Drag):
81
def calcCoord(self, frac):
82
(startX, startY) = self.startXY
83
(endX, endY) = self.endXY
84
#(deltaX, deltaY) = (endX-startX, endY-startY)
86
return ( (startX*(1.0-frac)) + (endX*frac), (startY*(1.0-frac)) + (endY*frac))
88
jigsaw = Jigsaw('victim.png')
90
jigsaw.makeDirectories()
92
command = jigsaw.makeCropCommand()
98
def prepareNautilusWindow(w):
99
viewMenu = w.menu("View")
101
# Ensure it's in icon view mode:
102
viewMenu.menuItem("View as Icons").click()
104
viewMenu.menuItem("Normal Size").click()
105
viewMenu.menuItem("Zoom In").click()
107
# Ensure we're in manual layout mode:
108
viewMenu.menu("Arrange Items").menuItem("Manually").click()
110
viewMenu.menuItem("Clean Up by Name").click()
114
piecesWindow = n.openPath(jigsaw.piecesPath)
115
resultWindow = n.openPath(jigsaw.resultPath)
117
prepareNautilusWindow (piecesWindow)
118
prepareNautilusWindow (resultWindow)
120
#FIXME: now need to get both on top, with sane sizes
123
iv = piecesWindow.iconView()
124
icons = iv.findChildren(IsAnIcon(), recursive=True)
126
matcher = re.compile('piece-(.*).png')
130
index = int(matcher.match(icon.name).group(1))
131
(x,y,w,h) = icon.extents
133
(dstX, dstY, dstW, dstH) = resultWindow.iconView().extents
135
(targetX, targetY) = jigsaw.targetLocation((dstX+100, dstY+100), index)
137
# FIXME: different drag routes!
138
drag = LinearDrag((x+w/2,y+h/2), (targetX+w/2,targetY+h/2))
141
# Drag out to select the entire collage:
142
(dstX, dstY, dstW, dstH) = resultWindow.iconView().extents
143
drag = LinearDrag((dstX+50, dstY+50), (dstX+500, dstY+500))
144
drag.doDrag(2.0, 500)
149
drag = LinearDrag((dstX+300, dstY+300), (dstX+600, dstY+600))
154
click(dstX+50, dstY+50, 1)
155
#viewMenu = resultWindow.menu("View")
156
#viewMenu.menuItem("Zoom In").click()
157
#viewMenu.menuItem("Zoom In").click()