diff options
author | Andreas Auras <yak54@gmx.net> | 2010-03-06 20:42:33 +0100 |
---|---|---|
committer | Andreas Auras <yak54@gmx.net> | 2010-03-06 20:42:33 +0100 |
commit | c6f5dd57a40a1f5be661225f183c87452bd2d2b4 (patch) | |
tree | 5cea23a39951a8a7511034df5380167173ecda87 | |
parent | 6cdccc1f115a8caa5ecf51d5529d37461103c92e (diff) | |
download | df10ch-atmolight-controller-c6f5dd57a40a1f5be661225f183c87452bd2d2b4.tar.gz df10ch-atmolight-controller-c6f5dd57a40a1f5be661225f183c87452bd2d2b4.tar.bz2 |
New Setup Version 3
Added support for Edge Weighting, Overscan and Analyze Size Parameters with visualisation
Improved area's painting
Improved controller error handling
Added display of controller error flags
Added echo test
Set config version 2
-rw-r--r-- | .cproject | 5 | ||||
-rw-r--r-- | .project | 2 | ||||
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | df10ch_setup.py | 4 | ||||
-rw-r--r-- | df10ch_setup_pkg/areas_dlg.py | 296 | ||||
-rw-r--r-- | df10ch_setup_pkg/bright_dlg.py | 1 | ||||
-rw-r--r-- | df10ch_setup_pkg/device_dlg.py | 89 | ||||
-rw-r--r-- | df10ch_setup_pkg/device_drv.py | 93 | ||||
-rw-r--r-- | df10ch_setup_pkg/layout_dlg.py | 87 | ||||
-rw-r--r-- | df10ch_setup_pkg/map_dlg.py | 1 | ||||
-rw-r--r-- | df10ch_setup_pkg/white_cal_dlg.py | 1 |
11 files changed, 443 insertions, 141 deletions
@@ -774,6 +774,7 @@ </profile> </scannerConfigBuildInfo> </storageModule> +<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> </cconfiguration> <cconfiguration id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.1825585251"> <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.1825585251" moduleId="org.eclipse.cdt.core.settings" name="USBAppl"> @@ -1546,6 +1547,7 @@ </profile> </scannerConfigBuildInfo> </storageModule> +<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> </cconfiguration> <cconfiguration id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.749902634"> <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.749902634" moduleId="org.eclipse.cdt.core.settings" name="PWMBoot"> @@ -2318,6 +2320,7 @@ </profile> </scannerConfigBuildInfo> </storageModule> +<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> </cconfiguration> <cconfiguration id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.749902634.870823668"> <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.749902634.870823668" moduleId="org.eclipse.cdt.core.settings" name="PWMAppl"> @@ -3090,6 +3093,7 @@ </profile> </scannerConfigBuildInfo> </storageModule> +<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> </cconfiguration> <cconfiguration id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.2018598583"> <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="de.innot.avreclipse.configuration.app.release.179373882.1868963946.2018598583" moduleId="org.eclipse.cdt.core.settings" name="Dist"> @@ -3862,6 +3866,7 @@ </profile> </scannerConfigBuildInfo> </storageModule> +<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> </cconfiguration> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> @@ -36,7 +36,7 @@ </dictionary> <dictionary> <key>org.eclipse.cdt.make.core.buildLocation</key> - <value>${workspace_loc:/df10ch}</value> + <value>${workspace_loc:/df10ch/pwm_appl}</value> </dictionary> <dictionary> <key>org.eclipse.cdt.make.core.cleanBuildTarget</key> @@ -88,8 +88,9 @@ Installation of DF10Ch setup program ------------------------------------ For running the DF10CH setup program you need a installed python environment version 2.6, -the python modules TKinter and PyUSB and a installed libusb library. -On debian based systems these are packages: python2.6, python-tk, python-usb, libusb-1.0-0 +the python modules TKinter, Image, ImageTk, ImageDraw and PyUSB and a installed libusb library. +On debian based systems these are packages: python2.6, python-tk, python-imaging, python-imaging-tk, +python-usb, libusb-1.0-0 You can start the program directly from this distribution directory with: diff --git a/df10ch_setup.py b/df10ch_setup.py index 4bb4b2b..d7eddf1 100644 --- a/df10ch_setup.py +++ b/df10ch_setup.py @@ -35,7 +35,7 @@ from df10ch_setup_pkg.white_cal_dlg import WhiteCalDialog from df10ch_setup_pkg.bright_dlg import BrightDialog import df10ch_setup_pkg.device_drv -TITLE = "DF10CH Setup V2" +TITLE = "DF10CH Setup V3" print parser = OptionParser(version=TITLE) parser.add_option("-s", "--simulate", action="store", type="int", dest="simulate", default=0, help="Set simulated number of DF10CH controller's") @@ -65,7 +65,7 @@ else: top.wm_attributes("-fullscreen", fullscreen) root.transient(top) -areasDlg = AreasDialog(top, width=width, height=height, bd=0, bg="black") +areasDlg = AreasDialog(top, width=width, height=height, bd=0) areasDlg.root.grid(row=0, column=0) setupDlg = SetupDialog(root) diff --git a/df10ch_setup_pkg/areas_dlg.py b/df10ch_setup_pkg/areas_dlg.py index 3eeb8c7..11d59f0 100644 --- a/df10ch_setup_pkg/areas_dlg.py +++ b/df10ch_setup_pkg/areas_dlg.py @@ -21,15 +21,36 @@ # from Tkinter import * +import Image +import ImageTk +import ImageDraw import device_drv class AreasDialog: def __init__(self, master=None, **args): + self.width = args["width"] + self.height = args["height"] + self.parent = master self.root = Canvas(master, **args) self.selectedArea = None self.selectCallbacks = list() + self.edgeWeighting = -1 + + def cvX(self, x): + return int((self.cvWidth * x) / self.aWidth) - def configAreas(self, numAreas): + def cvY(self, y): + return int((self.cvHeight * y) / self.aHeight) + + def cvXY(self, l): + r = list() + for i in range(0, len(l), 2): + r.append(self.cvX(l[i])) + r.append(self.cvY(l[i + 1])) + return r + + def configAreas(self, numAreas, overscan, analyzeSize): + self.edgeWeighting = -1 nTopLeft = numAreas[device_drv.AreaIndex("TopLeft")] nTopRight = numAreas[device_drv.AreaIndex("TopRight")] nBottomLeft = numAreas[device_drv.AreaIndex("BottomLeft")] @@ -41,168 +62,288 @@ class AreasDialog: nRight = numAreas[device_drv.AreaIndex("Right")] cv = self.root - size = 0 - width = int(cv["width"]) - height = int(cv["height"]) + + # Calculate overscan and resulting canvas size + ovx = (self.width * overscan) / 1000 + ovy = (self.height * overscan) / 1000 + width = self.width - 2 * ovx + height = self.height - 2 * ovy + self.cvWidth = width + self.cvHeight = height + + # Apply overscan and canvas size + cv["width"] = width + cv["height"] = height + cv["background"] = "black" + self.parent["padx"] = ovx + self.parent["pady"] = ovy + self.parent["background"] = "cyan" + # Calculate analyze window size + aWidth = (analyzeSize + 1) * 64 + aHeight = (aWidth * self.height) / self.width + self.aWidth = aWidth + self.aHeight = aHeight + + # Calculate number of areas for each border sTop = nTop + nTopLeft + nTopRight + sBottom = nBottom + nBottomLeft + nBottomRight + sLeft = nLeft + nTopLeft + nBottomLeft + sRight = nRight + nTopRight + nBottomRight + self.sTop = sTop + self.sBottom = sBottom + self.sLeft = sLeft + self.sRight = sRight + + # Calculate area width for each border if sTop: - topSize = int(width / sTop) - topSizeEnd = width - topSize * (sTop - 1) - if not size or topSize < size: - size = topSize + topSizeX = int(aWidth / sTop) + topLastX = int((aWidth * (sTop - 1)) / sTop) + else: + topSizeX = 0 + topLastX = 0 - sBottom = nBottom + nBottomLeft + nBottomRight if sBottom: - bottomSize = int(width / sBottom) - bottomSizeEnd = width - bottomSize * (sBottom - 1) - if not size or bottomSize < size: - size = bottomSize - - sLeft = nLeft + nTopLeft + nBottomLeft + bottomSizeX = int(aWidth / sBottom) + bottomLastX = int((aWidth * (sBottom - 1)) / sBottom) + else: + bottomSizeX = 0 + bottomLastX = 0 + if sLeft: - leftSize = int(height / sLeft) - leftSizeEnd = height - leftSize * (sLeft - 1) - if not size or leftSize < size: - size = leftSize - - sRight = nRight + nTopRight + nBottomRight + leftSizeY = int(aHeight / sLeft) + leftLastY = int((aHeight * (sLeft - 1)) / sLeft) + else: + leftSizeY = 0 + leftLastY = 0 + if sRight: - rightSize = int(height / sRight) - rightSizeEnd = height - rightSize * (sRight - 1) - if not size or rightSize < size: - size = rightSize - - if not size or int(width / 2) < size: - size = int(width / 2) - if not size or int(height / 2) < size: - size = int(height / 2) + rightSizeY = int(aHeight / sRight) + rightLastY = int((aHeight * (sRight - 1)) / sRight) + else: + rightSizeY = 0 + rightLastY = 0 + + # Calculate depth (border towards center length) for each border + topSizeY = int(aHeight / 2) + if leftSizeY and leftSizeY < topSizeY: + topSizeY = leftSizeY + if rightSizeY and rightSizeY < topSizeY: + topSizeY = rightSizeY + + bottomSizeY = aHeight - int(aHeight / 2) + if leftLastY > bottomSizeY: + bottomSizeY = leftLastY + if rightLastY > bottomSizeY: + bottomSizeY = rightLastY + + leftSizeX = int(aWidth / 2) + if topSizeX and topSizeX < leftSizeX: + leftSizeX = topSizeX + if bottomSizeX and bottomSizeX < leftSizeX: + leftSizeX = bottomSizeX + + rightSizeX = aWidth - int(aWidth / 2) + if topLastX > rightSizeX: + rightSizeX = topLastX + if bottomLastX > rightSizeX: + rightSizeX = bottomLastX + pTop = [ None ] * nTop x = 0 # top left corner if nTopLeft: - pTopLeft = [ 0, 0, topSize, 0, topSize, size, size, size, size, leftSize, 0, leftSize ] - x = topSize + pTopLeft = [ 0, 0, topSizeX, 0, topSizeX, topSizeY, leftSizeX, topSizeY, leftSizeX, leftSizeY, 0, leftSizeY ] + x = topSizeX elif nTop == 1: - pTop[0] = [ 0, 0, width, 0, width - size, size, size, size ] + pTop[0] = [ 0, 0, aWidth, 0, rightSizeX, topSizeY, leftSizeX, topSizeY ] elif nTop > 1: - pTop[0] = [ 0, 0, topSize, 0, topSize, size, size, size ] + pTop[0] = [ 0, 0, topSizeX, 0, topSizeX, topSizeY, leftSizeX, topSizeY ] # top right corner if nTopRight: - pTopRight = [ width, 0, width, rightSize, width - size, rightSize, width - size, size, width - topSizeEnd, size, width - topSizeEnd, 0 ] + pTopRight = [ aWidth, 0, aWidth, rightSizeY, rightSizeX, rightSizeY, rightSizeX, topSizeY, topLastX, topSizeY, topLastX, 0 ] elif nTop > 1: - pTop[nTop - 1] = [ width, 0, width - size, size, width - topSizeEnd, size, width - topSizeEnd, 0 ] + pTop[nTop - 1] = [ aWidth, 0, rightSizeX, topSizeY, topLastX, topSizeY, topLastX, 0 ] # top for i in range(nTop): + x2 = int((aWidth * (i + nTopLeft + 1)) / sTop) if pTop[i] == None: - pTop[i] = [ x, 0, x + topSize, 0, x + topSize, size, x, size ] - x = x + topSize + pTop[i] = [ x, 0, x2, 0, x2, topSizeY, x, topSizeY ] + x = x2 pBottom = [ None ] * nBottom x = 0 # bottom left corner if nBottomLeft: - pBottomLeft = [ 0, height, 0, height - leftSizeEnd, size, height - leftSizeEnd, size, height - size, bottomSize, height - size, bottomSize, height ] - x = bottomSize + pBottomLeft = [ 0, aHeight, 0, leftLastY, leftSizeX, leftLastY, leftSizeX, bottomSizeY, bottomSizeX, bottomSizeY, bottomSizeX, aHeight ] + x = bottomSizeX elif nBottom == 1: - pBottom[0] = [ 0, height, size, height - size, width - size, height - size, width, height ] + pBottom[0] = [ 0, aHeight, leftSizeX, bottomSizeY, rightSizeX, bottomSizeY, aWidth, aHeight ] elif nBottom > 1: - pBottom[0] = [ 0, height, size, height - size, bottomSize, height - size, bottomSize, height ] + pBottom[0] = [ 0, aHeight, leftSizeX, bottomSizeY, bottomSizeX, bottomSizeY, bottomSizeX, aHeight ] # bottom right corner if nBottomRight: - pBottomRight = [ width, height, width - bottomSizeEnd, height, width - bottomSizeEnd, height - size, width - size, height - size, width - size, height - rightSizeEnd, width, height - rightSizeEnd ] + pBottomRight = [ aWidth, aHeight, bottomLastX, aHeight, bottomLastX, bottomSizeY, rightSizeX, bottomSizeY, rightSizeX, rightLastY, aWidth, rightLastY ] elif nBottom > 1: - pBottom[nBottom - 1] = [ width, height, width - bottomSizeEnd, height, width - bottomSizeEnd, height - size, width - size, height - size ] + pBottom[nBottom - 1] = [ aWidth, aHeight, bottomLastX, aHeight, bottomLastX, bottomSizeY, rightSizeX, bottomSizeY ] # bottom for i in range(nBottom): + x2 = int((aWidth * (i + nBottomLeft + 1)) / sBottom) if pBottom[i] == None: - pBottom[i] = [ x, height, x, height - size, x + bottomSize, height - size, x + bottomSize, height ] - x = x + bottomSize + pBottom[i] = [ x, aHeight, x, bottomSizeY, x2, bottomSizeY, x2, aHeight ] + x = x2 pLeft = [ None ] * nLeft y = 0 # left top corner if nTopLeft: - y = leftSize + y = leftSizeY elif nLeft == 1: - pLeft[0] = [ 0, 0, size, size, size, height - size, 0, height ] + pLeft[0] = [ 0, 0, leftSizeX, topSizeY, leftSizeX, bottomSizeY, 0, aHeight ] elif nLeft > 1: - pLeft[0] = [ 0, 0, size, size, size, leftSize, 0, leftSize ] + pLeft[0] = [ 0, 0, leftSizeX, topSizeY, leftSizeX, leftSizeY, 0, leftSizeY ] # left bottom corner if not nBottomLeft and nLeft > 1: - pLeft[nLeft - 1] = [ 0, height, 0, height - leftSizeEnd, size, height - leftSizeEnd, size, height - size ] + pLeft[nLeft - 1] = [ 0, aHeight, 0, leftLastY, leftSizeX, leftLastY, leftSizeX, bottomSizeY ] # left for i in range(nLeft): + y2 = int((aHeight * (i + nTopLeft + 1)) / sLeft) if pLeft[i] == None: - pLeft[i] = [ 0, y, size, y, size, y + leftSize, 0, y + leftSize ] - y = y + leftSize + pLeft[i] = [ 0, y, leftSizeX, y, leftSizeX, y2, 0, y2 ] + y = y2 pRight = [ None ] * nRight y = 0 # right top corner if nTopRight: - y = rightSize + y = rightSizeY elif nRight == 1: - pRight[0] = [ width, 0, width, height, width - size, height - size, width - size, size ] + pRight[0] = [ aWidth, 0, aWidth, aHeight, rightSizeX, bottomSizeY, rightSizeX, topSizeY ] elif nRight > 1: - pRight[0] = [ width, 0, width, rightSize, width - size, rightSize, width - size, size ] + pRight[0] = [ aWidth, 0, aWidth, rightSizeY, rightSizeX, rightSizeY, rightSizeX, topSizeY ] # right bottom corner if not nBottomRight and nRight > 1: - pRight[nRight - 1] = [ width, height, width - size, height - size, width - size, height - rightSizeEnd, width, height - rightSizeEnd ] + pRight[nRight - 1] = [ aWidth, aHeight, rightSizeX, bottomSizeY, rightSizeX, rightLastY, aWidth, rightLastY ] # right for i in range(nRight): + y2 = int((aHeight * (i + nTopRight + 1)) / sRight) if pRight[i] == None: - pRight[i] = [ width, y, width, y + rightSize, width - size, y + rightSize, width - size, y ] - y = y + rightSize + pRight[i] = [ width, y, width, y2, rightSizeX, y2, rightSizeX, y ] + y = y2 # center if nCenter: - pCenter = [ size, size, width - size, size, width - size, height - size, size, height - size ] + pCenter = [ leftSizeX, topSizeY, rightSizeX, topSizeY, rightSizeX, bottomSizeY, leftSizeX, bottomSizeY ] # Build canvas items cv.delete(ALL) + + self.weightImg = Image.new("L", (width, height), color="black") + self.weightDraw = ImageDraw.Draw(self.weightImg) + cv.weightImg = ImageTk.PhotoImage(self.weightImg) + self.weightImgId = cv.create_image(0, 0, image=cv.weightImg, anchor=NW, state=HIDDEN) if nTopLeft: - cv.create_polygon(pTopLeft, tags="TopLeft") + cv.create_polygon(self.cvXY(pTopLeft), tags="TopLeft") if nTopRight: - cv.create_polygon(pTopRight, tags="TopRight") + cv.create_polygon(self.cvXY(pTopRight), tags="TopRight") if nBottomLeft: - cv.create_polygon(pBottomLeft, tags="BottomLeft") + cv.create_polygon(self.cvXY(pBottomLeft), tags="BottomLeft") if nBottomRight: - cv.create_polygon(pBottomRight, tags="BottomRight") + cv.create_polygon(self.cvXY(pBottomRight), tags="BottomRight") if nCenter: - cv.create_polygon(pCenter, tags="Center") + cv.create_polygon(self.cvXY(pCenter), tags="Center") for i in range(nTop): - cv.create_polygon(pTop[i], tags="Top-{0}".format(i + 1)) + cv.create_polygon(self.cvXY(pTop[i]), tags="Top-{0}".format(i + 1)) for i in range(nBottom): - cv.create_polygon(pBottom[i], tags="Bottom-{0}".format(i + 1)) + cv.create_polygon(self.cvXY(pBottom[i]), tags="Bottom-{0}".format(i + 1)) for i in range(nLeft): - cv.create_polygon(pLeft[i], tags="Left-{0}".format(i + 1)) + cv.create_polygon(self.cvXY(pLeft[i]), tags="Left-{0}".format(i + 1)) for i in range(nRight): - cv.create_polygon(pRight[i], tags="Right-{0}".format(i + 1)) + cv.create_polygon(self.cvXY(pRight[i]), tags="Right-{0}".format(i + 1)) for id in cv.find_all(): - cv.itemconfigure(id, outline="#808080", width=3) - cv.tag_bind(id, "<Button-1>", self.cbSelectArea) + if id != self.weightImgId: + cv.itemconfigure(id, fill="", outline="#808080", width=3) + cv.tag_bind(id, "<Button-1>", self.cbSelectArea) + + def calcEdgeWeighting(self, edgeWeighting): + w = float(edgeWeighting) / 10.0 + fHeight = float(self.aHeight - 1) + fWidth = float(self.aWidth - 1) + centerY = self.aHeight / 2 + centerX = self.aWidth / 2 + for y in range(self.aHeight): + yNorm = float(y) / fHeight + if self.sTop: + wTop = pow(1.0 - yNorm, w) + if self.sBottom: + wBottom = pow(yNorm, w) + for x in range(self.aWidth): + xNorm = float(x) / fWidth + weight = 0.0 + if self.sLeft and x < centerX: + weight = pow(1.0 - xNorm, w) + if self.sRight and x >= centerX: + weight = max(weight, pow(xNorm, w)) + if self.sTop and y < centerY: + weight = max(weight, wTop) + if self.sBottom and y >= centerY: + weight = max(weight, wBottom) + bright = int(255.0 * weight) + px = self.cvX(x) + px2 = self.cvX(x + 1) + py = self.cvY(y) + py2 = self.cvY(y + 1) + if bright > 32: + bBright = bright - 32 + else: + bBright = 0 + self.weightDraw.polygon([(px, py), (px2, py), (px2, py2), (px, py2)], fill=bright, outline=bBright) + self.root.weightImg.paste(self.weightImg) + self.edgeWeighting = edgeWeighting + + def showEdgeWeighting(self, edgeWeighting, topWin): + if self.edgeWeighting != edgeWeighting: + cursor = topWin["cursor"] + topWin["cursor"] = "watch" + self.root.update_idletasks() + self.calcEdgeWeighting(edgeWeighting) + topWin["cursor"] = cursor + if self.edgeWeighting == edgeWeighting: + self.root.itemconfigure(self.weightImgId, state=NORMAL) + def hideEdgeWeighting(self): + self.root.itemconfigure(self.weightImgId, state=HIDDEN) + + def resetAreas(self): + self.parent["background"] = "cyan" + self.root["background"] = "black" + for id in self.root.find_all(): + if id != self.weightImgId: + self.root.itemconfigure(id, fill="", outline="#808080") + self.selectedArea = None + def initAreas(self, color): - self.root.configure(background=color) + self.parent["background"] = color + self.root["background"] = color for id in self.root.find_all(): - self.root.itemconfigure(id, fill=color, outline="#808080") + if id != self.weightImgId: + self.root.itemconfigure(id, fill=color, outline="#808080") self.selectedArea = None def setAreaColor(self, area, color): @@ -225,11 +366,12 @@ class AreasDialog: idList = cv.find_closest(cv.canvasx(event.x), cv.canvasx(event.y)) if len(idList): id = idList[0] - if self.selectedArea: - cv.itemconfigure(self.selectedArea, outline="#808080") - self.selectedArea = cv.gettags(id)[0] - cv.tag_raise(id) - cv.itemconfigure(id, outline="yellow") + if id != self.weightImgId: + if self.selectedArea: + cv.itemconfigure(self.selectedArea, outline="#808080") + self.selectedArea = cv.gettags(id)[0] + cv.tag_raise(id) + cv.itemconfigure(id, outline="yellow") for cb in self.selectCallbacks: cb.cbAreaSelected() diff --git a/df10ch_setup_pkg/bright_dlg.py b/df10ch_setup_pkg/bright_dlg.py index 0bf8bf4..294c40a 100644 --- a/df10ch_setup_pkg/bright_dlg.py +++ b/df10ch_setup_pkg/bright_dlg.py @@ -70,6 +70,7 @@ class BrightDialog: tkMessageBox.showerror(self.root.winfo_toplevel().title(), err.__str__()) return + self.areasDlg.hideEdgeWeighting() self.areasDlg.initAreas("black") self.setBright() diff --git a/df10ch_setup_pkg/device_dlg.py b/df10ch_setup_pkg/device_dlg.py index 0d48f2e..d400b33 100644 --- a/df10ch_setup_pkg/device_dlg.py +++ b/df10ch_setup_pkg/device_dlg.py @@ -37,6 +37,7 @@ class DeviceDialog: self.layoutDlg = layoutDlg self.selectedConfig = None self.selectedDeviceIdx = -1 + self.echo_test_running = False root = Frame(master, **args) self.root = root @@ -74,29 +75,46 @@ class DeviceDialog: self.btScanDevices = Button(root, text="Scan Devices", command=self.cbScanDevices) self.btScanDevices.grid(row=5, column=0, padx=5, pady=5, ipadx=5) - self.btResetSetup = Button(root, text="Firmware update", command=self.cbFirmwareUpdate) - self.btResetSetup.grid(row=5, column=1, padx=5, pady=5, ipadx=5) + self.btShowStatus = Button(root, text="Show Status", command=self.cbShowStatus) + self.btShowStatus.grid(row=6, column=0, padx=5, pady=5, ipadx=5) self.btStoreSetup = Button(root, text="Backup", command=self.cbBackupSetup) - self.btStoreSetup.grid(row=5, column=2, padx=5, pady=5, ipadx=5, sticky=E) + self.btStoreSetup.grid(row=5, column=1, padx=5, pady=5, ipadx=5) self.btStoreSetup = Button(root, text="Restore", command=self.cbRestoreSetup) - self.btStoreSetup.grid(row=5, column=3, padx=5, pady=5, ipadx=5, sticky=W) + self.btStoreSetup.grid(row=6, column=1, padx=5, pady=5, ipadx=5) + + self.btResetSetup = Button(root, text="Firmware update", command=self.cbFirmwareUpdate) + self.btResetSetup.grid(row=5, column=2, columnspan=4, padx=5, pady=5, ipadx=5) + + self.btEchoTest = Button(root, text="Start echo test", command=self.cbEchoTest) + self.btEchoTest.grid(row=6, column=2, columnspan=4, padx=5, pady=5, ipadx=5) self.btResetSetup = Button(root, text="Reset Setup", command=self.cbResetSetup) - self.btResetSetup.grid(row=5, column=4, padx=5, pady=5, ipadx=5, sticky=E) + self.btResetSetup.grid(row=5, column=6, padx=5, pady=5, ipadx=5) self.btStoreSetup = Button(root, text="Store Setup", command=self.cbStoreSetup) - self.btStoreSetup.grid(row=5, column=5, padx=5, pady=5, ipadx=5, sticky=W) + self.btStoreSetup.grid(row=6, column=6, padx=5, pady=5, ipadx=5) self.varStatus = StringVar() self.lbStatus = Label(root, textvariable=self.varStatus, anchor=W, relief=RIDGE) - self.lbStatus.grid(row=6, column=0, columnspan=6, padx=0, pady=0, sticky=W+E) + self.lbStatus.grid(row=7, column=0, columnspan=7, padx=0, pady=0, sticky=W+E) def cbSheetSelected(self, event): if self.selectedConfig: self.loadDeviceValues() + + def cbShowStatus(self): + if len(device_drv.DeviceList): + self.showStatus() + + def cbEchoTest(self): + if self.echo_test_running: + self.echo_test_running = False + else: + if self.selectedDeviceIdx != -1: + self.echoTest() def cbFirmwareUpdate(self): if len(device_drv.DeviceList): @@ -146,24 +164,27 @@ class DeviceDialog: self.scanDevices() def scanDevices(self): - deviceList = None self.selectedConfig = None self.selectedDeviceIdx = -1 - while not deviceList: + retry = True + while retry: try: device_drv.LoadConfigs() - if len(device_drv.DeviceList): - deviceList = device_drv.DeviceList except (device_drv.AtmoControllerError, usb.USBError) as err: if not tkMessageBox.askretrycancel(self.root.winfo_toplevel().title(), "Scanning for controllers fails:" + err.__str__(), icon=tkMessageBox.ERROR): - return False + if len(device_drv.DeviceList): + retry = False + else: + return False else: - if not deviceList: + if len(device_drv.DeviceList): + retry = False + else: if not tkMessageBox.askretrycancel(self.root.winfo_toplevel().title(), "No Controllers found!", icon=tkMessageBox.ERROR): return False idList = "" - for dev in deviceList: + for dev in device_drv.DeviceList: if len(idList) > 0: idList = idList + " " idList = idList + dev.id @@ -426,3 +447,43 @@ class DeviceDialog: def displayStatus(self, msg): self.varStatus.set(msg) self.root.update_idletasks() + + def showStatus(self): + msg = "" + for dev in device_drv.DeviceList: + request_stat = "N/A" + reply_stat = "N/A" + try: + rc = dev.get_reply_error_status() + except device_drv.AtmoControllerError as err: + pass + else: + reply_stat = device_drv.GetCommErrMsg(rc) + + try: + rc = dev.get_request_error_status() + except device_drv.AtmoControllerError as err: + pass + else: + request_stat = device_drv.GetCommErrMsg(rc) + + msg = msg + "{0}: ERR:{1} USB:{2} PWM:{3}\n".format(dev.id, dev.error_count, reply_stat, request_stat) + tkMessageBox.showinfo(self.root.winfo_toplevel().title() + " Communication status", msg) + + def echoTest(self): + self.echo_test_running = True + self.btEchoTest['text'] = "Stop echo test" + dev = device_drv.DeviceList[self.selectedDeviceIdx] + testValue = 0 + while testValue < 0x7FFFFFFF: + self.varStatus.set("Testing {0}: {1}".format(dev.id, testValue)) + self.root.update() + if not self.echo_test_running: + break + try: + dev.pwm_echo_test(testValue) + except device_drv.AtmoControllerError as err: + tkMessageBox.showerror(self.root.winfo_toplevel().title(), err.__str__()) + testValue = testValue + 1 + self.varStatus.set("") + self.btEchoTest['text'] = "Start echo test" diff --git a/df10ch_setup_pkg/device_drv.py b/df10ch_setup_pkg/device_drv.py index cf00272..8941df7 100644 --- a/df10ch_setup_pkg/device_drv.py +++ b/df10ch_setup_pkg/device_drv.py @@ -233,13 +233,25 @@ def GetCommErrMsg(stat): CONFIG_VALID_ID = 0xA0A1 -CONFIG_VERSION = 0x0001 -CONFIG_CLASS_VERSION = 0x0001 +CONFIG_VERSION = 0x0002 +CONFIG_CLASS_VERSION = 0x0002 DEFAULT_GAMMA_VAL = 22 MIN_GAMMA_VAL = 10 MAX_GAMMA_VAL = 50 +DEFAULT_OVERSCAN = 30 +MIN_OVERSCAN = 0 +MAX_OVERSCAN = 200 + +DEFAULT_EDGE_WEIGHTING = 80 +MIN_EDGE_WEIGHTING = 10 +MAX_EDGE_WEIGHTING = 200 + +DEFAULT_ANALYZE_SIZE = 1 +MIN_ANALYZE_SIZE = 0 +MAX_ANALYZE_SIZE = 5 + AREA_NAMES = "Top", "Bottom", "Left", "Right", "Center", "TopLeft", "TopRight", "BottomLeft", "BottomRight" MAX_AREAS = 30, 30, 30, 30, 1, 1, 1, 1, 1 @@ -297,7 +309,8 @@ class DF10CHController: self.version = version self.serial = serial self.id = 'DF10CH[{0},{1}]'.format(self.busnum, self.devnum) - + self.error_count = 0 + def release(self): self.usbdev.releaseInterface() @@ -310,11 +323,14 @@ class DF10CHController: retry = retry - 1 written = self.usbdev.controlMsg(usb.ENDPOINT_OUT|usb.RECIP_DEVICE|usb.TYPE_VENDOR, req, data, value, index, timeout) except usb.USBError as err: + self.error_count = self.error_count + 1 + print 'write req={0}, retry={1}: {2}'.format(req, retry, err.__str__()) if retry == 0: - raise AtmoControllerError(self, err.__str__()) + raise AtmoControllerError(self, 'write req={0}: {1}'.format(req, err.__str__())) else: if written != len(data): - raise AtmoControllerError(self, 'could not write all payload data to device') + self.error_count = self.error_count + 1 + raise AtmoControllerError(self, 'write req={0}: could not write all payload data'.format(req)) break def ctrl_read(self, req, value = 0, index = 0, size = 0, timeout = DEF_USB_TIMEOUT, retry = DEF_RETRY): @@ -323,27 +339,33 @@ class DF10CHController: retry = retry - 1 data = self.usbdev.controlMsg(usb.ENDPOINT_IN|usb.RECIP_DEVICE|usb.TYPE_VENDOR, req, size, value, index, timeout) except usb.USBError as err: + print 'read req={0}, retry={1}: {2}'.format(req, retry, err.__str__()) if retry == 0: - raise AtmoControllerError(self, err.__str__()) + self.error_count = self.error_count + 1 + raise AtmoControllerError(self, 'read req={0}: {1}'.format(req, err.__str__())) else: if len(data) != size: - raise AtmoControllerError(self, 'could not read all payload data') + self.error_count = self.error_count + 1 + raise AtmoControllerError(self, 'read req={0}: could not read all payload data'.format(req)) break return data def pwm_ctrl_write(self, req, value, index, data, timeout = DEF_USB_TIMEOUT, retry = DEF_RETRY): if len(data) > MAX_PWM_REQ_PAYLOAD_SIZE: + self.error_count = self.error_count + 1 raise AtmoControllerError(self, 'to many bytes in payload request data') self.ctrl_write(req, value, index, data, timeout, retry) def pwm_ctrl_read(self, req, value = 0, index = 0, size = 0, timeout = DEF_USB_TIMEOUT, retry = DEF_RETRY): if size > MAX_PWM_REPLY_PAYLOAD_SIZE: + self.error_count = self.error_count + 1 raise AtmoControllerError(self, 'to many bytes for reply payload data') return self.ctrl_read(req, value, index, size, timeout, retry) def verify_reply_data(self, start, data, rdata, msg): for i in range(len(data)): if data[i] != rdata[i]: + self.error_count = self.error_count + 1 raise AtmoControllerError(self, '{4}: verify of written {3} data fails {0:04X}: write {1:02X} read {2:02X}'.format(start + i, data[i], rdata[i], msg, self.id)) def read_ee_data(self, start, size): @@ -461,6 +483,13 @@ class DF10CHController: data = self.pwm_ctrl_read(PWM_REQ_GET_VERSION, 0, 0, 2) return data[1] + def pwm_echo_test(self, testValue): + v = testValue & 0x0FFFF + i = testValue >> 16 + data = self.pwm_ctrl_read(PWM_REQ_ECHO_TEST, v, i, 8) + if (data[2] + data[3] * 256) != v or (data[4] + data[5] * 256) != i: + raise AtmoControllerError(self, 'echo test fails for value {0}'.format(testValue)) + def get_pwm_flash_page_size(self): data = self.pwm_ctrl_read(BL_PWM_REQ_GET_PAGE_SIZE, 0, 0, 2) return data[0] + data[1] * 256 @@ -493,6 +522,7 @@ class dummyController: self.flash = dict() self.pwm_vers = PWM_VERS_APPL self.pwm_flash = dict() + self.error_count = 0 def _reset_setup(self): self.common_bright = NCOMMONBRIGHTS - 1 @@ -618,6 +648,9 @@ class dummyController: def get_pwm_version(self): return 1 + def pwm_echo_test(self, testValue): + pass + def get_bootloader_request_error_status(self): return 0 @@ -668,23 +701,36 @@ class ControllerConfig: self.commonPWMRes = self.ctrl.get_common_max_pwm_value() self.pwmFreq = self.ctrl.get_pwm_freq() self.commonBright = self.ctrl.get_common_brightness() + self.configVersion = 0 self.numAreas = [ 0 ] * NumBaseAreas() - - eedata = self.ctrl.read_ee_data(1, 5 + len(self.numAreas) + NCHANNELS * 6) + self.numReqChannels = 0 + self.analyzeSize = DEFAULT_ANALYZE_SIZE + self.edgeWeighting = DEFAULT_EDGE_WEIGHTING + self.overscan = DEFAULT_OVERSCAN + + eedata = self.ctrl.read_ee_data(1, 8 + len(self.numAreas) + NCHANNELS * 6) #print "read eedata:", eedata configValidId = eedata[0] + eedata[1] * 256 if configValidId == CONFIG_VALID_ID: - configVersion = "{0:04X}".format(eedata[2] + eedata[3] * 256) - for p in range(len(self.numAreas)): - self.numAreas[p] = eedata[4 + p] - if self.numAreas[p] > MAX_AREAS[p]: self.numAreas = MAX_AREAS[p] + self.configVersion = eedata[2] + eedata[3] * 256 + configVersionStr = "{0:04X}".format(self.configVersion) + p = 4 + for i in range(len(self.numAreas)): + self.numAreas[i] = min(eedata[p], MAX_AREAS[i]) + p = p + 1 + self.numReqChannels = min(eedata[p], NCHANNELS) + p = p + 1 + if self.configVersion > 1: + p = p + self.numReqChannels * 6 + self.overscan = max(min(eedata[p], MAX_OVERSCAN), MIN_OVERSCAN) + self.analyzeSize = max(min(eedata[p + 1], MAX_ANALYZE_SIZE), MIN_ANALYZE_SIZE) + self.edgeWeighting = max(min(eedata[p + 2], MAX_EDGE_WEIGHTING), MIN_EDGE_WEIGHTING) else: - configVersion = "" - self.version = "USB:{0} PWM:{1:04X} CONFIG:{2}".format(self.ctrl.version, self.ctrl.get_pwm_version(), configVersion) + configVersionStr = "" + self.version = "USB:{0} PWM:{1:04X} CONFIG:{2}".format(self.ctrl.version, self.ctrl.get_pwm_version(), configVersionStr) pwmChannelMap = self.ctrl.get_channel_map(0, NCHANNELS) #print "read pwmChannelMap", pwmChannelMap self.channelMap = dict() - self.numReqChannels = 0 for portName in PORT_NAME_MAP.keys(): foundArea = None port, pin = PORT_NAME_MAP[portName] @@ -694,21 +740,15 @@ class ControllerConfig: outPins = channelRec['pins'] if outPort == port and (outPins & pin): if configValidId == CONFIG_VALID_ID: - p = 4 + len(self.numAreas) - self.numReqChannels = eedata[p] - if self.numReqChannels > NCHANNELS: self.numReqChannels = 0 - p = p + 1 + p = 5 + len(self.numAreas) for i in range(self.numReqChannels): if eedata[p] == reqChannel: area = AreaName(eedata[p + 1], eedata[p + 2]) if area: foundArea = area color = eedata[p + 1] & 0x03 - gamma = eedata[p + 3] - if gamma < MIN_GAMMA_VAL: gamma = MIN_GAMMA_VAL - if gamma > MAX_GAMMA_VAL: gamma = MAX_GAMMA_VAL - whiteCal = eedata[p + 4] + eedata[p + 5] * 256 - if whiteCal > self.pwmRes: whiteCal = self.pwmRes + gamma = max(min(eedata[p + 3], MAX_GAMMA_VAL), MIN_GAMMA_VAL) + whiteCal = min((eedata[p + 4] + eedata[p + 5] * 256), self.pwmRes) break p = p + 6 break @@ -757,6 +797,9 @@ class ControllerConfig: pwmChannelMap.append(dict(channel=reqChannel, port=port, pins=pin)) eedata[4 + len(self.numAreas)] = n + eedata.append(self.overscan) + eedata.append(self.analyzeSize) + eedata.append(self.edgeWeighting) self.numReqChannels = 0 while len(pwmChannelMap) < NCHANNELS: diff --git a/df10ch_setup_pkg/layout_dlg.py b/df10ch_setup_pkg/layout_dlg.py index 500c029..7fc9ed7 100644 --- a/df10ch_setup_pkg/layout_dlg.py +++ b/df10ch_setup_pkg/layout_dlg.py @@ -29,36 +29,37 @@ import device_drv class LayoutDialog: def __init__(self, areasDlg, master=None, **args): self.areasDlg = areasDlg + self.edgeWeighting = 0 + self.analyzeSize = 0 + self.overscan = 0 self.numAreas = [ 0 ] * device_drv.NumBaseAreas() - self.varNumAreas = list() - for i in range(device_drv.NumBaseAreas()): - self.varNumAreas.append(StringVar()) root = Frame(master, **args) self.root = root + root.bind("<Map>", self.cbSheetSelected) - Label(root, text="Configure RGB-Areas", font=tkFont.Font(weight="bold")).grid(row=0, column=0, columnspan=5, padx=5, pady=5) - Label(root, text="Top").grid(row=1, column=2) - Label(root, text="TopLeft").grid(row=1, column=0, sticky=E) - Label(root, text="Left").grid(row=3, column=0, sticky=E) - Label(root, text="BottomLeft").grid(row=5, column=0, sticky=E) - Label(root, text="TopRight").grid(row=1, column=4, sticky=W) - Label(root, text="Right").grid(row=3, column=4, sticky=W) - Label(root, text="BottomRight").grid(row=5, column=4, sticky=W) - Label(root, text="Bottom").grid(row=5, column=2) + Label(root, text="Configure RGB-Areas", font=tkFont.Font(weight="bold")).grid(row=0, column=0, columnspan=8, padx=5, pady=5) + self.varNumAreas = list() + for i in range(device_drv.NumBaseAreas()): + self.varNumAreas.append(StringVar()) + + Label(root, text="TopLeft").grid(row=1, column=0, sticky=E) i = device_drv.AreaIndex("TopLeft") self.sbTopLeft = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], width=2) self.sbTopLeft.grid(row=2, column=1, padx=5, pady=5) + Label(root, text="TopRight").grid(row=1, column=4, sticky=W) i = device_drv.AreaIndex("TopRight") self.sbTopRight = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], width=2) self.sbTopRight.grid(row=2, column=3, padx=5, pady=5) + Label(root, text="BottomLeft").grid(row=5, column=0, sticky=E) i = device_drv.AreaIndex("BottomLeft") self.sbBottomLeft = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], width=2) self.sbBottomLeft.grid(row=4, column=1, padx=5, pady=5) + Label(root, text="BottomRight").grid(row=5, column=4, sticky=W) i = device_drv.AreaIndex("BottomRight") self.sbBottomRight = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], width=2) self.sbBottomRight.grid(row=4, column=3, padx=5, pady=5) @@ -67,45 +68,91 @@ class LayoutDialog: self.sbCenter = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], width=2) self.sbCenter.grid(row=3, column=2, padx=20, pady=20) + Label(root, text="Top").grid(row=1, column=2) i = device_drv.AreaIndex("Top") self.sbTop = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], increment=1, width=3) self.sbTop.grid(row=2, column=2, padx=5, pady=5) + Label(root, text="Bottom").grid(row=5, column=2) i = device_drv.AreaIndex("Bottom") self.sbBottom = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], increment=1, width=3) self.sbBottom.grid(row=4, column=2, padx=5, pady=5) + Label(root, text="Left").grid(row=3, column=0, sticky=E) i = device_drv.AreaIndex("Left") self.sbLeft = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], increment=1, width=3) self.sbLeft.grid(row=3, column=1, padx=5, pady=5) + Label(root, text="Right").grid(row=3, column=4, sticky=W) i = device_drv.AreaIndex("Right") self.sbRight = Spinbox(root, textvariable=self.varNumAreas[i], from_=0, to=device_drv.MAX_AREAS[i], increment=1, width=3) self.sbRight.grid(row=3, column=3, padx=5, pady=5) + Label(root, text="Overscan [%1000]:").grid(row=2, column=6, sticky=E) + self.varOverscan = StringVar() + self.sbOverscan = Spinbox(root, textvariable=self.varOverscan, from_=device_drv.MIN_OVERSCAN, to=device_drv.MAX_OVERSCAN, increment=1, width=4) + self.sbOverscan.grid(row=2, column=7, padx=5, pady=5, sticky=W) + + Label(root, text="Analyze window size:").grid(row=3, column=6, sticky=E) + self.varAnalyzeSize = StringVar() + self.sbAnalyzeSize = Spinbox(root, textvariable=self.varAnalyzeSize, from_=device_drv.MIN_ANALYZE_SIZE, to=device_drv.MAX_ANALYZE_SIZE, increment=1, width=4) + self.sbAnalyzeSize.grid(row=3, column=7, padx=5, pady=5, sticky=W) + + Label(root, text="Edge weighting:").grid(row=4, column=6, sticky=E) + self.varWeight = StringVar() + self.sbWeight = Spinbox(root, textvariable=self.varWeight, from_=device_drv.MIN_EDGE_WEIGHTING, to=device_drv.MAX_EDGE_WEIGHTING, increment=1, width=4) + self.sbWeight.grid(row=4, column=7, padx=5, pady=5, sticky=W) + + self.btShowEdgeWeighting = Button(root, text="Show edge weighting", command=self.cbShowEdgeWeighting) + self.btShowEdgeWeighting.grid(row=6, column=0, columnspan=7, padx=20, pady=20, ipadx=5, sticky=E) + self.btApply = Button(root, text="Apply", command=self.cbApply) - self.btApply.grid(row=6, column=4, padx=20, pady=20, ipadx=5) + self.btApply.grid(row=6, column=7, columnspan=1, padx=20, pady=20, ipadx=5, sticky=E) + def cbSheetSelected(self, event): + self.areasDlg.resetAreas() + + def cbShowEdgeWeighting(self): + self.applyValues() + self.areasDlg.showEdgeWeighting(self.edgeWeighting, self.root.winfo_toplevel()) + def cbApply(self): + self.applyValues() + + def applyValues(self): for i in range(device_drv.NumBaseAreas()): self.numAreas[i] = int(self.varNumAreas[i].get()) - self.areasDlg.configAreas(self.numAreas) - + self.overscan = int(self.varOverscan.get()) + self.analyzeSize = int(self.varAnalyzeSize.get()) + self.edgeWeighting = int(self.varWeight.get()) + self.areasDlg.configAreas(self.numAreas, self.overscan, self.analyzeSize) + def setLayoutFromConfig(self): - for i in range(device_drv.NumBaseAreas()): - self.numAreas[i] = 0 + self.analyzeSize = 0 + self.edgeWeighting = 0 + self.overscan = 0 + self.numAreas = [ 0 ] * device_drv.NumBaseAreas() for ctrlId in device_drv.ConfigMap.keys(): config = device_drv.ConfigMap[ctrlId] + self.overscan = config.overscan + self.analyzeSize = config.analyzeSize + self.edgeWeighting = config.edgeWeighting for i in range(device_drv.NumBaseAreas()): if config.numAreas[i] > self.numAreas[i]: self.numAreas[i] = config.numAreas[i] for i in range(device_drv.NumBaseAreas()): self.varNumAreas[i].set(self.numAreas[i]) - self.areasDlg.configAreas(self.numAreas) - + self.varOverscan.set(self.overscan) + self.varAnalyzeSize.set(self.analyzeSize) + self.varWeight.set(self.edgeWeighting) + self.areasDlg.configAreas(self.numAreas, self.overscan, self.analyzeSize) + def setConfigFromLayout(self): for ctrlId in device_drv.ConfigMap.keys(): config = device_drv.ConfigMap[ctrlId] + config.overscan = self.overscan + config.analyzeSize = self.analyzeSize + config.edgeWeighting = self.edgeWeighting for i in range(device_drv.NumBaseAreas()): config.numAreas[i] = self.numAreas[i] - + diff --git a/df10ch_setup_pkg/map_dlg.py b/df10ch_setup_pkg/map_dlg.py index b8cd575..c91564b 100644 --- a/df10ch_setup_pkg/map_dlg.py +++ b/df10ch_setup_pkg/map_dlg.py @@ -206,6 +206,7 @@ class ChannelMapDialog: tkMessageBox.showerror(self.root.winfo_toplevel().title(), err.__str__()) return + self.areasDlg.hideEdgeWeighting() self.areasDlg.initAreas("black") self.actualCtrlId = None self.actualPortName = None diff --git a/df10ch_setup_pkg/white_cal_dlg.py b/df10ch_setup_pkg/white_cal_dlg.py index 3843e78..5f1f8b7 100644 --- a/df10ch_setup_pkg/white_cal_dlg.py +++ b/df10ch_setup_pkg/white_cal_dlg.py @@ -123,6 +123,7 @@ class WhiteCalDialog: tkMessageBox.showerror(self.root.winfo_toplevel().title(), err.__str__()) return + self.areasDlg.hideEdgeWeighting() if area: self.selectArea(area) self.setBright() |