Beispiel #1
0
	def __init__(self):
		# Create a component checker
		self.componentChecker = {}
		self.configFile = os.path.expanduser('~/rcmanager.xml')
		# Gui config
		global dict
		QtGui.QDialog.__init__(self)
		self.root = '/opt/robocomp/'
		self.ui = Ui_Form()
		self.ui.setupUi(self)
		self.canvas = GraphView(self.ui.graphTab)
		self.canvas.setGeometry(0, 0, 531, 581)
		self.canvas.show()
		self.canvasTimer = QtCore.QTimer()
		self.canvasFastTimer = QtCore.QTimer()
		self.connect(self.canvas, QtCore.SIGNAL("nodeReleased()"), self.setFastState)
		self.setFastState(True)
		self.connect(self.canvasTimer, QtCore.SIGNAL("timeout()"), self.graphUpdate)
		self.connect(self.canvasFastTimer, QtCore.SIGNAL("timeout()"), self.graphFastEnds)
		if dict['dock'] == 'true':
			self.changeDock()

		# Variables needed to switch the state of components when double-clicking over them.
		self.clickTimes = 0
		self.lastClickTime = QtCore.QTime()
		self.clickNumber = -1

		# Component config containter
		self.compConfig = []

		# Init component sets
		self.back_comps = set()
		self.requests = set()

		# Icon and system's tray stuff
		self.iconOK = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_red.png'))
		self.iconFULL = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_green.png'))
		self.iconChange1 = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_right.png'))
		self.iconChange2 = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_left.png'))
		self.setWindowIcon(self.iconOK)
		self.state = 0
		self.doExit = False
		self.systray = None
		self.blinkTimer = QtCore.QTimer()
		self.doDock = False

		# Set the fixed timeout for component checking
		self.timer = QtCore.QTimer()
		self.timer.start(dict['fixed'])


		self.menu = QtGui.QMenuBar(None)
		self.ui.verticalLayout_3.insertWidget(0, self.menu)
		self.menuFile = self.menu.addMenu('File')
		self.menuSim = self.menu.addMenu('Simulation')
		self.menuActions = self.menu.addMenu('Actions')

		self.actionKillAll = self.menuActions.addAction('kill all')
		self.connect(self.actionKillAll, QtCore.SIGNAL("triggered(bool)"), self.killall)
		#self.actionRunAll = self.menuActions.addAction('run all')
		#self.connect(self.actionRunAll, QtCore.SIGNAL("triggered(bool)"), self.runall)

		self.actionOpen = self.menuFile.addAction('Open')
		self.connect(self.actionOpen, QtCore.SIGNAL("triggered(bool)"), self.openFile)
		self.actionSave = self.menuFile.addAction('Save')
		self.connect(self.actionSave, QtCore.SIGNAL("triggered(bool)"), self.saveFile)
		self.actionEdit = self.menuFile.addAction('Edit')
		self.connect(self.actionEdit, QtCore.SIGNAL("triggered(bool)"), self.runEditor)
		self.actionDock = self.menuFile.addAction('Dock')
		self.connect(self.actionDock, QtCore.SIGNAL("triggered(bool)"), self.changeDock)
		self.actionExit = self.menuFile.addAction('Exit')
		self.connect(self.actionExit, QtCore.SIGNAL("triggered(bool)"), self.forceExit)

		# Do we want the eye-candy graph simulation?
		if (dict['active'] == "true"):
			self.doSimulation = True
		else:
			self.doSimulation = False
		if self.doSimulation == True:
			self.actionSS = self.menuSim.addAction('Stop')
		else:
			self.actionSS = self.menuSim.addAction('Start')

		# Set connections
		self.connect(self.ui.checkList, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.selectCheck)
		self.connect(self.ui.upButton, QtCore.SIGNAL("clicked()"), self.up)
		self.connect(self.ui.downButton, QtCore.SIGNAL("clicked()"), self.down)
		self.connect(self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"), self.tabChanged)
		self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.checkAll)
		self.connect(self.canvas, QtCore.SIGNAL('upRequest()'), self.manageGraphUp)
		self.connect(self.canvas, QtCore.SIGNAL('downRequest()'), self.manageGraphDown)
		self.connect(self.canvas, QtCore.SIGNAL('configRequest()'), self.manageGraphConfig)
		self.connect(self.actionSS, QtCore.SIGNAL("triggered(bool)"), self.sSimulation)

		# Draw the graph
		self.canvas.update()

		# Get settings
		settings = QtCore.QSettings("RoboComp", "rcmanager")
		value = settings.value("geometry").toByteArray()
		if value != None:
			self.restoreGeometry(value)
		value = settings.value("page").toInt()
		if value != None:
			if value[1] == True:
				self.ui.tabWidget.setCurrentIndex(value[0])
		value = settings.value("docking").toBool()
		if value != None:
			if value == True:
				self.changeDock()
Beispiel #2
0
	def __init__(self):
		# Create a component checker
		self.componentChecker = ComponentChecker()
		self.configFile = os.path.expanduser('~/rcmanager.xml')
		# Gui config
		global dict
		QtGui.QDialog.__init__(self)
		self.root = '/opt/robocomp/'
		self.ui = Ui_Form()
		self.ui.setupUi(self)
		self.canvas = GraphView(self.ui.graphTab)
		self.canvas.setGeometry(0, 0, 531, 581)
		self.connect(self.canvas, QtCore.SIGNAL("nodeReleased()"), self.setFastState)
		self.canvas.show()
		self.canvasTimer = QtCore.QTimer()
		self.canvasFastTimer = QtCore.QTimer()
		self.connect(self.canvasTimer, QtCore.SIGNAL("timeout()"), self.graphUpdate)
		self.connect(self.canvasFastTimer, QtCore.SIGNAL("timeout()"), self.graphFastEnds)
		if dict['dock'] == 'true':
			self.changeDock()

		# Variables needed to switch the state of components when double-clicking over them.
		self.clickTimes = 0
		self.lastClickTime = QtCore.QTime()
		self.clickNumber = -1

		# Component config containter
		self.compConfig = []

		# Init component sets
		self.back_comps = set()
		self.requests = set()

		# Icon and system's tray stuff
		self.iconOK = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_red.png'))
		self.iconFULL = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_green.png'))
		self.iconChange1 = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_right.png'))
		self.iconChange2 = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_left.png'))
		self.setWindowIcon(self.iconOK)
		self.state = 0
		self.doExit = False
		self.systray = None
		self.blinkTimer = QtCore.QTimer()
		self.doDock = False

		# Make an initial check
		self.checkAll(initial=True)

		# Set the fixed timeout for component checking
		self.timer = QtCore.QTimer()
		self.timer.start(dict['fixed'])


		self.menu = QtGui.QMenuBar(self)
		self.menu.setFixedWidth(300);
		self.menuFile = self.menu.addMenu('File')
		self.menuSim = self.menu.addMenu('Simulation')

		self.actionOpen = self.menuFile.addAction('Open')
		self.connect(self.actionOpen, QtCore.SIGNAL("triggered(bool)"), self.openFile)
		self.actionSave = self.menuFile.addAction('Save')
		self.connect(self.actionSave, QtCore.SIGNAL("triggered(bool)"), self.saveFile)
		self.actionEdit = self.menuFile.addAction('Edit')
		self.connect(self.actionEdit, QtCore.SIGNAL("triggered(bool)"), self.runEditor)
		self.actionDock = self.menuFile.addAction('Dock')
		self.connect(self.actionDock, QtCore.SIGNAL("triggered(bool)"), self.changeDock)
		self.actionExit = self.menuFile.addAction('Exit')
		self.connect(self.actionExit, QtCore.SIGNAL("triggered(bool)"), self.forceExit)

		# Do we want the eye-candy graph simulation?
		if (dict['active'] == "true"):
			self.doSimulation = True
		else:
			self.doSimulation = False
		if self.doSimulation == True:
			self.actionSS = self.menuSim.addAction('Stop')
		else:
			self.actionSS = self.menuSim.addAction('Start')

		# Set connections
		self.connect(self.ui.checkList, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.selectCheck)
		self.connect(self.ui.upButton, QtCore.SIGNAL("clicked()"), self.up)
		self.connect(self.ui.downButton, QtCore.SIGNAL("clicked()"), self.down)
		self.connect(self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"), self.tabChanged)
		self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.checkAll)
		self.connect(self.canvas, QtCore.SIGNAL('upRequest()'), self.manageGraphUp)
		self.connect(self.canvas, QtCore.SIGNAL('downRequest()'), self.manageGraphDown)
		self.connect(self.canvas, QtCore.SIGNAL('configRequest()'), self.manageGraphConfig)
		self.connect(self.actionSS, QtCore.SIGNAL("triggered(bool)"), self.sSimulation)

		# Draw the graph
		self.canvas.update()

		# Get settings
		settings = QtCore.QSettings("RoboComp", "rcmanager")
		value = settings.value("geometry").toByteArray()
		if value != None:
			self.restoreGeometry(value)
		value = settings.value("page").toInt()
		if value != None:
			if value[1] == True:
				self.ui.tabWidget.setCurrentIndex(value[0])
		value = settings.value("docking").toBool()
		if value != None:
			if value == True:
				self.changeDock()
Beispiel #3
0
class TheThing(QtGui.QDialog):
	def __init__(self):
		# Create a component checker
		self.componentChecker = {}
		self.configFile = os.path.expanduser('~/rcmanager.xml')
		# Gui config
		global dict
		QtGui.QDialog.__init__(self)
		self.root = '/opt/robocomp/'
		self.ui = Ui_Form()
		self.ui.setupUi(self)
		self.canvas = GraphView(self.ui.graphTab)
		self.canvas.setGeometry(0, 0, 531, 581)
		self.canvas.show()
		self.canvasTimer = QtCore.QTimer()
		self.canvasFastTimer = QtCore.QTimer()
		self.connect(self.canvas, QtCore.SIGNAL("nodeReleased()"), self.setFastState)
		self.setFastState(True)
		self.connect(self.canvasTimer, QtCore.SIGNAL("timeout()"), self.graphUpdate)
		self.connect(self.canvasFastTimer, QtCore.SIGNAL("timeout()"), self.graphFastEnds)
		if dict['dock'] == 'true':
			self.changeDock()

		# Variables needed to switch the state of components when double-clicking over them.
		self.clickTimes = 0
		self.lastClickTime = QtCore.QTime()
		self.clickNumber = -1

		# Component config containter
		self.compConfig = []

		# Init component sets
		self.back_comps = set()
		self.requests = set()

		# Icon and system's tray stuff
		self.iconOK = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_red.png'))
		self.iconFULL = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_green.png'))
		self.iconChange1 = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_right.png'))
		self.iconChange2 = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_left.png'))
		self.setWindowIcon(self.iconOK)
		self.state = 0
		self.doExit = False
		self.systray = None
		self.blinkTimer = QtCore.QTimer()
		self.doDock = False

		# Set the fixed timeout for component checking
		self.timer = QtCore.QTimer()
		self.timer.start(dict['fixed'])


		self.menu = QtGui.QMenuBar(None)
		self.ui.verticalLayout_3.insertWidget(0, self.menu)
		self.menuFile = self.menu.addMenu('File')
		self.menuSim = self.menu.addMenu('Simulation')
		self.menuActions = self.menu.addMenu('Actions')

		self.actionKillAll = self.menuActions.addAction('kill all')
		self.connect(self.actionKillAll, QtCore.SIGNAL("triggered(bool)"), self.killall)
		#self.actionRunAll = self.menuActions.addAction('run all')
		#self.connect(self.actionRunAll, QtCore.SIGNAL("triggered(bool)"), self.runall)

		self.actionOpen = self.menuFile.addAction('Open')
		self.connect(self.actionOpen, QtCore.SIGNAL("triggered(bool)"), self.openFile)
		self.actionSave = self.menuFile.addAction('Save')
		self.connect(self.actionSave, QtCore.SIGNAL("triggered(bool)"), self.saveFile)
		self.actionEdit = self.menuFile.addAction('Edit')
		self.connect(self.actionEdit, QtCore.SIGNAL("triggered(bool)"), self.runEditor)
		self.actionDock = self.menuFile.addAction('Dock')
		self.connect(self.actionDock, QtCore.SIGNAL("triggered(bool)"), self.changeDock)
		self.actionExit = self.menuFile.addAction('Exit')
		self.connect(self.actionExit, QtCore.SIGNAL("triggered(bool)"), self.forceExit)

		# Do we want the eye-candy graph simulation?
		if (dict['active'] == "true"):
			self.doSimulation = True
		else:
			self.doSimulation = False
		if self.doSimulation == True:
			self.actionSS = self.menuSim.addAction('Stop')
		else:
			self.actionSS = self.menuSim.addAction('Start')

		# Set connections
		self.connect(self.ui.checkList, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.selectCheck)
		self.connect(self.ui.upButton, QtCore.SIGNAL("clicked()"), self.up)
		self.connect(self.ui.downButton, QtCore.SIGNAL("clicked()"), self.down)
		self.connect(self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"), self.tabChanged)
		self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.checkAll)
		self.connect(self.canvas, QtCore.SIGNAL('upRequest()'), self.manageGraphUp)
		self.connect(self.canvas, QtCore.SIGNAL('downRequest()'), self.manageGraphDown)
		self.connect(self.canvas, QtCore.SIGNAL('configRequest()'), self.manageGraphConfig)
		self.connect(self.actionSS, QtCore.SIGNAL("triggered(bool)"), self.sSimulation)

		# Draw the graph
		self.canvas.update()

		# Get settings
		settings = QtCore.QSettings("RoboComp", "rcmanager")
		value = settings.value("geometry").toByteArray()
		if value != None:
			self.restoreGeometry(value)
		value = settings.value("page").toInt()
		if value != None:
			if value[1] == True:
				self.ui.tabWidget.setCurrentIndex(value[0])
		value = settings.value("docking").toBool()
		if value != None:
			if value == True:
				self.changeDock()

	# Select a new rcmanager configuration file
	def openFile(self, p=None):
		if p==None:
			self.configFile = QtGui.QFileDialog.getOpenFileName (self, "Select file", initDir, "*.xml")
		else:
			self.configFile = p

		if len(self.configFile) > 0:
			if self.canvas.ui != None: self.canvas.ui.close()
			self.readConfig()
		else:
			print 'len(cfgFile) == 0'


	# Save the current configuration to a new file
	def saveFile(self):
		global dict
		if self.canvas.ui != None: self.canvas.ui.close()
		s = QtGui.QFileDialog.getSaveFileName (self, "Select output file", os.environ['HOME'], "*.xml")
		if len(s) > 0:
			for c1 in self.compConfig:
				for c2 in self.canvas.compList:
					if c1.alias == c2.name:
						c1.x = c2.x
						c1.y = c2.y
						c1.r = c2.r
			rcmanagerConfig.writeConfigToFile(dict, self.compConfig, s)

	# Dock icon blinking method.
	def changeDock(self):
		global dict
		if self.canvas.ui != None: self.canvas.ui.close()
		if self.doDock == False:
			self.systray = QtGui.QSystemTrayIcon(self)
			self.systray.setIcon(self.iconOK)
			self.systray.setVisible(True)
			self.connect(self.systray, QtCore.SIGNAL("activated (QSystemTrayIcon::ActivationReason)"), self.toggle)
			self.connect(self.blinkTimer, QtCore.SIGNAL("timeout()"), self.changeIcon)
			self.iconNumber = 0
			self.doDock = True
			dict['dock'] = 'true'
			self.actionDock.setText('Undock')
		else:
			self.systray.deleteLater()
			self.disconnect(self.blinkTimer, QtCore.SIGNAL("timeout()"), self.changeIcon)
			self.iconNumber = 0
			self.doDock = False
			dict['dock'] = 'false'
			self.actionDock.setText('Dock')

	# Stop graph simulation if its running or vice versa.
	def sSimulation(self):
		global dict
		self.doSimulation = not self.doSimulation
		if self.doSimulation == False:
			self.actionSS.setText('Start')
			if self.fastState == False:
				self.canvasTimer.start(dict['focustime'])
			dict['active'] = 'false'
		else:
			self.actionSS.setText('Stop')
			self.setFastState()
			if self.fastState == False:
				self.canvasTimer.start(dict['idletime'])
			dict['active'] = 'true'

	# When doing simulation calling this method will make the simulation go fast
	def setFastState(self, fast=True):
		global dict
		self.fastState = fast
		if fast:
			self.canvasTimer.start(dict['fasttime'])
			self.canvasFastTimer.start(dict['fastperiod'])
		else:
			self.canvasFastTimer.stop()
			if self.ui.tabWidget.currentIndex() == 1 and self.doSimulation == True:
				self.canvasTimer.start(dict['focustime'])
			else:
				self.canvasTimer.start(dict['idletime'])

	# Opposite of the previous method
	def graphFastEnds(self):
		self.setFastState(False)

	# Run component simulator
	def runEditor(self):
		if self.canvas.ui != None: self.canvas.ui.close()
		self.editor = rcmanagerEditor.rcmanagerEditorWidget()
		self.editor.setModal(True)
		self.editor.show()
		self.editor.readConfig(self.configFile)
		self.connect(self.editor, QtCore.SIGNAL('finished()'), self.readConfig)

	# Add the ui-selected component to the requests set by calling the 'up()' method.
	def manageGraphUp(self):
		for idx in range(self.ui.checkList.count()):
			if self.ui.checkList.item(idx).text() == self.canvas.request:
				self.ui.checkList.setCurrentRow(idx)
				self.selectCheck()
				self.up()
				break

	# Add the ui-selected component to the down set by calling the 'down()' method.
	def manageGraphDown(self):
		for idx in range(self.ui.checkList.count()):
			if self.ui.checkList.item(idx).text() == self.canvas.request:
				self.ui.checkList.setCurrentRow(idx)
				self.selectCheck()
				self.down()
				break

	# Edit a component's configuration
	def manageGraphConfig(self):
		for idx in range(self.ui.checkList.count()):
			if self.ui.checkList.item(idx).text() == self.canvas.request:
				self.ui.checkList.setCurrentRow(idx)
				self.selectCheck()
				self.config()
				break

	# Update the UI graph
	def graphUpdate(self):
		global dict
		self.canvas.checkForNewComponents(self)

		self.canvas.center()
		if self.doSimulation:
			self.canvas.step(self)
		self.canvas.update()

	# Current tab changed
	@QtCore.pyqtSignature("int")
	def tabChanged(self, num):
		if self.fastState == False:
			if num == 0: self.canvasTimer.start(dict['idletime'])
			elif num == 1 and self.doSimulation == True: self.canvasTimer.start(dict['focustime'])

	# Retuns True if the specified component is up, otherwise returns False
	def itsUp(self, compNumber):
		if self.compConfig[compNumber].alias in self.componentChecker:
			return self.componentChecker[self.compConfig[compNumber]].isalive()
		return False

	# Queues the user's request to change the state of a given component, turning it off if it's on and viceversa.
	def switchComponent(self, compNumber):
		if self.itsUp(compNumber) == True: self.down()
		else: self.up()

	# Queues the user request to turn on a component
	def up(self):
		itsconfig = self.compConfig[self.ui.checkList.currentRow()]
		self.requests = self.requests | set([itsconfig.alias])
		self.clearFocus()

	# Queues the user request to turn off a component
	def down(self):
		self.bg_exec(str(self.ui.downEdit.text()), self.ui.wdEdit.text())
		self.clearFocus()

	def killall(self):
		for info in self.compConfig:
			self.bg_exec(str(info.compdown), str(info.workingdir))

	# Run the configured file editor
	def config(self):
		global dict
		self.bg_exec(self.compConfig[self.ui.checkList.currentRow()].configFile, self.ui.wdEdit.text())
		self.clearFocus()

	# Reads new configuration from file
	def readConfig(self):
		self.canvas.initialize()
		self.ui.checkList.clear()
		self.compConfig = []
		self.back_comps = set()
		self.requests = set()

		newList, newDict = rcmanagerConfig.getConfigFromFile(self.configFile)

		for k, v in newDict.iteritems():
			dict[k] = v

		self.componentChecker.clear()
		for listItem in newList:
			item = QtGui.QListWidgetItem()
			item.setText(listItem.alias)
			self.ui.checkList.insertItem(0, item)
			self.compConfig.insert(0, listItem)
			self.componentChecker[listItem.alias] = ComponentChecker(listItem.endpoint)
			self.componentChecker[listItem.alias].runrun()

		self.log('Configuration loaded')

		n = rcmanagerConfig.unconnectedGroups(newList)
		if n > 1:
			msg = 'WARNING: ' + str(n) + ' unconnected component groups'
			self.log(msg)
			QtGui.QMessageBox.warning(self, 'Warning', msg)
		self.setFastState()

		# Call-back when



	#
	def selectCheck(self):
		# Check if it's a consecutive click
		notTheLastOneAtTime = 0
		if self.clickNumber != self.ui.checkList.currentRow():
			notTheLastOneAtTime = 1
		if self.lastClickTime.elapsed() > dict['interval']:
			notTheLastOneAtTime = 1
		if notTheLastOneAtTime == 0:                   # It's not
			self.clickTimes = self.clickTimes + 1
		else:                                          # It is
			self.clickTimes = 1
		self.clickNumber = self.ui.checkList.currentRow()
		self.lastClickTime = self.lastClickTime.currentTime()
		# If it's a N-ary click: swap its state
		if self.clickTimes >= dict['switch']:
			self.switchComponent(self.clickNumber)
		# Show information of the last clicked component
		info = self.compConfig[self.ui.checkList.currentRow()]
		self.ui.checkEdit.setText(info.endpoint)
		self.ui.wdEdit.setText(info.workingdir)
		self.ui.upEdit.setText(info.compup)
		self.ui.downEdit.setText(info.compdown)
		self.ui.cfgEdit.setText(info.configFile)

	def checkAll(self, initial=False):
		allOk = True
		workingComponents = set()
		for numItem in range(0, len(self.compConfig)):
			ok = True
			itemConfig = self.compConfig[numItem]
			item = self.ui.checkList.item(numItem)
			if (itemConfig.alias in self.componentChecker) and (self.componentChecker[itemConfig.alias].isalive()):
				item.setTextColor(QtGui.QColor(0, 255, 0))
				workingComponents.add(itemConfig.alias)
			else:
				item.setTextColor(QtGui.QColor(255, 0, 0))
				allOk = False

		if workingComponents != self.back_comps:
			if allOk == False:
				self.blinkTimer.stop()
				self.blinkTimer.start(dict['blink'])

		for comp in workingComponents.difference(self.back_comps):
			self.log('Now \"' + comp + '\" is up.')
		for comp in self.back_comps.difference(workingComponents):
			self.log('Now \"' + comp + '\" is down.')

		if self.wantsDocking():
			if allOk and len(self.compConfig) > 0:
				self.systray.setIcon(self.iconFULL)
			elif workingComponents != self.back_comps:
				self.systray.setIcon(self.iconOK)

		self.back_comps = workingComponents.copy()
		self.upRequests()

	def upRequests(self):
		future_requests = self.requests
		for alias in self.requests:
			itsconfig = self.getConfigByAlias(alias)
			unavailableDependences = []
			for dep in itsconfig.dependences:
				if (not dep in self.componentChecker) or (not self.componentChecker[dep].isalive()):
					unavailableDependences.append(dep)
			if len(unavailableDependences) == 0:
				print 'rcmanager:', alias, 'is now ready to run.'
				self.upConfig(itsconfig)
				future_requests = future_requests - set([alias])
			else:
				print 'rcmanager:', alias, 'has unavailable dependences:', unavailableDependences
				future_requests = future_requests | set(unavailableDependences)
		self.requests = future_requests


	# Tries to execute a component
	def upConfig(self, conf):
		self.bg_exec(conf.compup, conf.workingdir)


	# Executes a command in the background
	def bg_exec(self, command, workDir):
		# Get command argument list
		argument_list = command.split(' ')
		# Set program as argument_list[0]
		program = argument_list[0]
		# Set args as argument_list[1, -1]
		args = argument_list[1:]

		currentWorkDir = os.getcwd()
		os.chdir(workDir)
		proc = QtCore.QProcess()
		print '\nQProcess::startDetached( ' + program + ' , ' + str(args) + ' ) @ ' + os.getcwd() + '\n'
		proc.startDetached(program, args)
		os.chdir(currentWorkDir)

	#
	# Changes the icon of the program properly, skipping if docking is not active
	def changeIcon(self):
		if self.isActiveWindow() == True:
			self.blinkTimer.stop()
			self.systray.setIcon(self.iconOK)
		else:
			if self.iconNumber == 0:
				self.systray.setIcon(self.iconChange1)
				self.iconNumber = 1
			elif self.iconNumber == 1:
				self.systray.setIcon(self.iconChange2)
				self.iconNumber = 2
			else:
				self.systray.setIcon(self.iconChange1)
				self.iconNumber = 1
	#
	# (Un)hide the main window
	def toggle(self):
		if self.isVisible(): self.hide()
		else: self.show()
	#
	# Manages close events
	def closeEvent(self, closeevent):
		settings = QtCore.QSettings("RoboComp", "rcmanager");
		g = self.saveGeometry()
		settings.setValue("geometry", QtCore.QVariant(g))
		settings.setValue("page", QtCore.QVariant(self.ui.tabWidget.currentIndex()))
		settings.setValue("docking", QtCore.QVariant(self.wantsDocking()))
		if self.doExit != 1 and self.doDock == True:
			closeevent.ignore()
			self.hide()
		elif self.wantsDocking():
			closeevent.accept()
			for key, checker in self.componentChecker.iteritems():
				checker.stop()
#		else:
#			closeevent.accept()
#			self.forceExit()
#			sys.exit(0)


	#
	# Forces the program to exit
	def forceExit(self):
		self.doExit = 1
		self.close()
	#
	# Clears the interface selection when the user presses 'Esc'
	def keyPressEvent(self, keyevent):
		if keyevent.key() == 16777216:#0x01000000
			self.ui.checkList.clearSelection()
			if self.canvas.ui != None: self.canvas.ui.close()
	#
	# Interface stuff:
	def uiChange(self):
		self.ui.checkList.setCurrentRow(0)
		self.selectCheck()
		self.clearFocus()
	def clearFocus(self):
		self.ui.checkList.clearSelection()
	def log(self, text):
		self.ui.outputText.append(' * ' + QtCore.QTime.currentTime().toString() + ': ' + text)
	def getConfigByAlias(self, alias):
		for config in self.compConfig:
			if config.alias == alias:
				return config
		return None
	#
	# Return 1 if docking is selected, 0 otherwise.
	def wantsDocking(self):
		if self.doDock == True: return 1
		else: return 0
	def resizeEvent(self, e):
		old = e.oldSize()
		new = e.size()
		inc = new - old
		if (inc.width != 0 or inc.height!=0):
			self.canvas.resize(self.canvas.size()+inc)
		e.accept()
Beispiel #4
0
class TheThing(QtGui.QDialog):
	def __init__(self):
		# Create a component checker
		self.componentChecker = ComponentChecker()
		self.configFile = os.path.expanduser('~/rcmanager.xml')
		# Gui config
		global dict
		QtGui.QDialog.__init__(self)
		self.root = '/opt/robocomp/'
		self.ui = Ui_Form()
		self.ui.setupUi(self)
		self.canvas = GraphView(self.ui.graphTab)
		self.canvas.setGeometry(0, 0, 531, 581)
		self.connect(self.canvas, QtCore.SIGNAL("nodeReleased()"), self.setFastState)
		self.canvas.show()
		self.canvasTimer = QtCore.QTimer()
		self.canvasFastTimer = QtCore.QTimer()
		self.connect(self.canvasTimer, QtCore.SIGNAL("timeout()"), self.graphUpdate)
		self.connect(self.canvasFastTimer, QtCore.SIGNAL("timeout()"), self.graphFastEnds)
		if dict['dock'] == 'true':
			self.changeDock()

		# Variables needed to switch the state of components when double-clicking over them.
		self.clickTimes = 0
		self.lastClickTime = QtCore.QTime()
		self.clickNumber = -1

		# Component config containter
		self.compConfig = []

		# Init component sets
		self.back_comps = set()
		self.requests = set()

		# Icon and system's tray stuff
		self.iconOK = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_red.png'))
		self.iconFULL = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_green.png'))
		self.iconChange1 = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_right.png'))
		self.iconChange2 = QtGui.QIcon(QtGui.QPixmap('/opt/robocomp/share/rcmanager/drawing_left.png'))
		self.setWindowIcon(self.iconOK)
		self.state = 0
		self.doExit = False
		self.systray = None
		self.blinkTimer = QtCore.QTimer()
		self.doDock = False

		# Make an initial check
		self.checkAll(initial=True)

		# Set the fixed timeout for component checking
		self.timer = QtCore.QTimer()
		self.timer.start(dict['fixed'])


		self.menu = QtGui.QMenuBar(self)
		self.menu.setFixedWidth(300);
		self.menuFile = self.menu.addMenu('File')
		self.menuSim = self.menu.addMenu('Simulation')

		self.actionOpen = self.menuFile.addAction('Open')
		self.connect(self.actionOpen, QtCore.SIGNAL("triggered(bool)"), self.openFile)
		self.actionSave = self.menuFile.addAction('Save')
		self.connect(self.actionSave, QtCore.SIGNAL("triggered(bool)"), self.saveFile)
		self.actionEdit = self.menuFile.addAction('Edit')
		self.connect(self.actionEdit, QtCore.SIGNAL("triggered(bool)"), self.runEditor)
		self.actionDock = self.menuFile.addAction('Dock')
		self.connect(self.actionDock, QtCore.SIGNAL("triggered(bool)"), self.changeDock)
		self.actionExit = self.menuFile.addAction('Exit')
		self.connect(self.actionExit, QtCore.SIGNAL("triggered(bool)"), self.forceExit)

		# Do we want the eye-candy graph simulation?
		if (dict['active'] == "true"):
			self.doSimulation = True
		else:
			self.doSimulation = False
		if self.doSimulation == True:
			self.actionSS = self.menuSim.addAction('Stop')
		else:
			self.actionSS = self.menuSim.addAction('Start')

		# Set connections
		self.connect(self.ui.checkList, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.selectCheck)
		self.connect(self.ui.upButton, QtCore.SIGNAL("clicked()"), self.up)
		self.connect(self.ui.downButton, QtCore.SIGNAL("clicked()"), self.down)
		self.connect(self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"), self.tabChanged)
		self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.checkAll)
		self.connect(self.canvas, QtCore.SIGNAL('upRequest()'), self.manageGraphUp)
		self.connect(self.canvas, QtCore.SIGNAL('downRequest()'), self.manageGraphDown)
		self.connect(self.canvas, QtCore.SIGNAL('configRequest()'), self.manageGraphConfig)
		self.connect(self.actionSS, QtCore.SIGNAL("triggered(bool)"), self.sSimulation)

		# Draw the graph
		self.canvas.update()

		# Get settings
		settings = QtCore.QSettings("RoboComp", "rcmanager")
		value = settings.value("geometry").toByteArray()
		if value != None:
			self.restoreGeometry(value)
		value = settings.value("page").toInt()
		if value != None:
			if value[1] == True:
				self.ui.tabWidget.setCurrentIndex(value[0])
		value = settings.value("docking").toBool()
		if value != None:
			if value == True:
				self.changeDock()

	# Select a new rcmanager configuration file
	def openFile(self, p=None):
		if p==None:
			self.configFile = QtGui.QFileDialog.getOpenFileName (self, "Select file", initDir, "*.xml")
		else:
			self.configFile = p

		if len(self.configFile) > 0:
			if self.canvas.ui != None: self.canvas.ui.close()
			self.readConfig()
		else:
			print 'len(cfgFile) == 0'


	# Save the current configuration to a new file
	def saveFile(self):
		global dict
		if self.canvas.ui != None: self.canvas.ui.close()
		s = QtGui.QFileDialog.getSaveFileName (self, "Select output file", os.environ['HOME'], "*.xml")
		if len(s) > 0:
			for c1 in self.compConfig:
				for c2 in self.canvas.compList:
					if c1.alias == c2.name:
						c1.x = c2.x
						c1.y = c2.y
						c1.r = c2.r
			rcmanagerConfig.writeConfigToFile(dict, self.compConfig, s)

	# Dock icon blinking method.
	def changeDock(self):
		global dict
		if self.canvas.ui != None: self.canvas.ui.close()
		if self.doDock == False:
			self.systray = QtGui.QSystemTrayIcon(self)
			self.systray.setIcon(self.iconOK)
			self.systray.setVisible(True)
			self.connect(self.systray, QtCore.SIGNAL("activated (QSystemTrayIcon::ActivationReason)"), self.toggle)
			self.connect(self.blinkTimer, QtCore.SIGNAL("timeout()"), self.changeIcon)
			self.iconNumber = 0
			self.doDock = True
			dict['dock'] = 'true'
			self.actionDock.setText('Undock')
		else:
			self.systray.deleteLater()
			self.disconnect(self.blinkTimer, QtCore.SIGNAL("timeout()"), self.changeIcon)
			self.iconNumber = 0
			self.doDock = False
			dict['dock'] = 'false'
			self.actionDock.setText('Dock')

	# Stop graph simulation if its running or vice versa.
	def sSimulation(self):
		global dict
		self.doSimulation = not self.doSimulation
		if self.doSimulation == False:
			self.actionSS.setText('Start')
			if self.fastState == False:
				self.canvasTimer.start(dict['focustime'])
			dict['active'] = 'false'
		else:
			self.actionSS.setText('Stop')
			self.setFastState()
			if self.fastState == False:
				self.canvasTimer.start(dict['idletime'])
			dict['active'] = 'true'

	# When doing simulation calling this method will make the simulation go fast
	def setFastState(self, fast=True):
		global dict
		self.fastState = fast
		if fast:
			self.canvasTimer.start(dict['fasttime'])
			self.canvasFastTimer.start(dict['fastperiod'])
		else:
			self.canvasFastTimer.stop()
			if self.ui.tabWidget.currentIndex() == 1 and self.doSimulation == True:
				self.canvasTimer.start(dict['focustime'])
			else:
				self.canvasTimer.start(dict['idletime'])

	# Opposite of the previous method
	def graphFastEnds(self):
		self.setFastState(False)

	# Run component simulator
	def runEditor(self):
		if self.canvas.ui != None: self.canvas.ui.close()
		self.editor = rcmanagerEditor.rcmanagerEditorWidget()
		self.editor.setModal(True)
		self.editor.show()
		self.editor.readConfig(self.configFile)
		self.connect(self.editor, QtCore.SIGNAL('finished()'), self.readConfig)

	# Add the ui-selected component to the requests set by calling the 'up()' method.
	def manageGraphUp(self):
		for idx in range(self.ui.checkList.count()):
			if self.ui.checkList.item(idx).text() == self.canvas.request:
				self.ui.checkList.setCurrentRow(idx)
				self.selectCheck()
				self.up()
				break

	# Add the ui-selected component to the down set by calling the 'down()' method.
	def manageGraphDown(self):
		for idx in range(self.ui.checkList.count()):
			if self.ui.checkList.item(idx).text() == self.canvas.request:
				self.ui.checkList.setCurrentRow(idx)
				self.selectCheck()
				self.down()
				break

	# Edit a component's configuration
	def manageGraphConfig(self):
		for idx in range(self.ui.checkList.count()):
			if self.ui.checkList.item(idx).text() == self.canvas.request:
				self.ui.checkList.setCurrentRow(idx)
				self.selectCheck()
				self.config()
				break

	# Update the UI graph
	def graphUpdate(self):
		global dict
		self.canvas.checkForNewComponents(self)

		self.canvas.center()
		if self.doSimulation:
			self.canvas.step(self)
		self.canvas.update()

	# Current tab changed
	@QtCore.pyqtSignature("int")
	def tabChanged(self, num):
		if self.fastState == False:
			if num == 0: self.canvasTimer.start(dict['idletime'])
			elif num == 1 and self.doSimulation == True: self.canvasTimer.start(dict['focustime'])

	# Retuns True if the specified component is up, otherwise returns False
	def itsUp(self, compNumber):
		if self.componentChecker.workingComponents.__contains__(self.compConfig[compNumber].alias): return True
		return False

	# Queues the user's request to change the state of a given component, turning it off if it's on and viceversa.
	def switchComponent(self, compNumber):
		if self.itsUp(compNumber) == True: self.down()
		else: self.up()

	# Queues the user request to turn on a component
	def up(self):
		itsconfig = self.compConfig[self.ui.checkList.currentRow()]
		self.requests = self.requests | set([itsconfig.alias])
		self.clearFocus()

	# Queues the user request to turn off a component
	def down(self):
		self.bg_exec(str(self.ui.downEdit.text()), self.ui.wdEdit.text())
		self.clearFocus()

	# Run the configured file editor
	def config(self):
		global dict
		self.bg_exec(self.compConfig[self.ui.checkList.currentRow()].configFile, self.ui.wdEdit.text())
		self.clearFocus()

	# Reads new configuration from file
	def readConfig(self):
		self.canvas.initialize()
		self.ui.checkList.clear()
		self.compConfig = []
		self.back_comps = set()
		self.requests = set()

		newList, newDict = rcmanagerConfig.getConfigFromFile(self.configFile)

		for k, v in newDict.iteritems():
			dict[k] = v

		self.componentChecker.reset()
		for listItem in newList:
			item = QtGui.QListWidgetItem()
			item.setText(listItem.alias)
			self.ui.checkList.insertItem(0, item)
			self.compConfig.insert(0, listItem)
			self.componentChecker.componentsToCheck[listItem.alias] = listItem.endpoint
		self.componentChecker.runrun()

		self.log('Configuration loaded')

		n = rcmanagerConfig.unconnectedGroups(newList)
		if n > 1:
			msg = 'WARNING: ' + str(n) + ' unconnected component groups'
			self.log(msg)
			QtGui.QMessageBox.warning(self, 'Warning', msg)
		self.setFastState()

		# Call-back when



	#
	def selectCheck(self):
		# Check if it's a consecutive click
		notTheLastOneAtTime = 0
		if self.clickNumber != self.ui.checkList.currentRow():
			notTheLastOneAtTime = 1
		if self.lastClickTime.elapsed() > dict['interval']:
			notTheLastOneAtTime = 1
		if notTheLastOneAtTime == 0:                   # It's not
			self.clickTimes = self.clickTimes + 1
		else:                                          # It is
			self.clickTimes = 1
		self.clickNumber = self.ui.checkList.currentRow()
		self.lastClickTime = self.lastClickTime.currentTime()
		# If it's a N-ary click: swap its state
		if self.clickTimes >= dict['switch']:
			self.switchComponent(self.clickNumber)
		# Show information of the last clicked component
		info = self.compConfig[self.ui.checkList.currentRow()]
		self.ui.checkEdit.setText(info.endpoint)
		self.ui.wdEdit.setText(info.workingdir)
		self.ui.upEdit.setText(info.compup)
		self.ui.downEdit.setText(info.compdown)
		self.ui.cfgEdit.setText(info.configFile)

	def checkAll(self, initial=False):
		allOk = True
		for numItem in range(0, len(self.compConfig)):
			ok = True
			itemConfig = self.compConfig[numItem]
			item = self.ui.checkList.item(numItem)
			if self.componentChecker.workingComponents.__contains__(itemConfig.alias):
				item.setTextColor(QtGui.QColor(0, 255, 0))
			else:
				item.setTextColor(QtGui.QColor(255, 0, 0))
				allOk = False

		if self.componentChecker.workingComponents != self.back_comps:
			if allOk == False:
				self.blinkTimer.stop()
				self.blinkTimer.start(dict['blink'])

		for comp in self.componentChecker.workingComponents.difference(self.back_comps):
			self.log('Now \"' + comp + '\" is up.')
		for comp in self.back_comps.difference(self.componentChecker.workingComponents):
			self.log('Now \"' + comp + '\" is down.')

		if self.wantsDocking():
			if allOk and len(self.compConfig) > 0:
				self.systray.setIcon(self.iconFULL)
			elif self.componentChecker.workingComponents != self.back_comps:
				self.systray.setIcon(self.iconOK)

		self.back_comps = self.componentChecker.workingComponents.copy()
		self.upRequests()

	def upRequests(self):
		future_requests = self.requests
		for alias in self.requests:
			itsconfig = self.getConfigByAlias(alias)
			unavailableDependences = []
			for dep in itsconfig.dependences:
				if not self.componentChecker.workingComponents.__contains__(dep):
					unavailableDependences.append(dep)
			if len(unavailableDependences) == 0:
				print 'rcmanager:', alias, 'is now ready to run.'
				self.upConfig(itsconfig)
				future_requests = future_requests - set([alias])
			else:
				print 'rcmanager:', alias, 'has unavailable dependences:', unavailableDependences
				future_requests = future_requests | set(unavailableDependences)
		self.requests = future_requests


	# Tries to execute a component
	def upConfig(self, conf):
		self.bg_exec(conf.compup, conf.workingdir)


	# Executes a command in the background
	def bg_exec(self, command, workDir):
		# Get command argument list
		argument_list = command.split(' ')
		# Set program as argument_list[0]
		program = argument_list[0]
		# Set args as argument_list[1, -1]
		args = argument_list[1:]

		currentWorkDir = os.getcwd()
		os.chdir(workDir)
		proc = QtCore.QProcess()
		print '\nQProcess::startDetached( ' + program + ' , ' + str(args) + ' ) @ ' + os.getcwd() + '\n'
		proc.startDetached(program, args)
		os.chdir(currentWorkDir)

	#
	# Changes the icon of the program properly, skipping if docking is not active
	def changeIcon(self):
		if self.isActiveWindow() == True:
			self.blinkTimer.stop()
			self.systray.setIcon(self.iconOK)
		else:
			if self.iconNumber == 0:
				self.systray.setIcon(self.iconChange1)
				self.iconNumber = 1
			elif self.iconNumber == 1:
				self.systray.setIcon(self.iconChange2)
				self.iconNumber = 2
			else:
				self.systray.setIcon(self.iconChange1)
				self.iconNumber = 1
	#
	# (Un)hide the main window
	def toggle(self):
		if self.isVisible(): self.hide()
		else: self.show()
	#
	# Manages close events
	def closeEvent(self, closeevent):
		settings = QtCore.QSettings("RoboComp", "rcmanager");
		g = self.saveGeometry()
		settings.setValue("geometry", QtCore.QVariant(g))
		settings.setValue("page", QtCore.QVariant(self.ui.tabWidget.currentIndex()))
		settings.setValue("docking", QtCore.QVariant(self.wantsDocking()))
		if self.doExit != 1 and self.doDock == True:
			closeevent.ignore()
			self.hide()
		elif self.wantsDocking():
			closeevent.accept()
			self.componentChecker.stop()
#		else:
#			closeevent.accept()
#			self.forceExit()
#			sys.exit(0)
		self.componentChecker.exit = True


	#
	# Forces the program to exit
	def forceExit(self):
		self.doExit = 1
		self.close()
	#
	# Clears the interface selection when the user presses 'Esc'
	def keyPressEvent(self, keyevent):
		if keyevent.key() == 16777216:#0x01000000
			self.ui.checkList.clearSelection()
			if self.canvas.ui != None: self.canvas.ui.close()
	#
	# Interface stuff:
	def uiChange(self):
		self.ui.checkList.setCurrentRow(0)
		self.selectCheck()
		self.clearFocus()
	def clearFocus(self):
		self.ui.checkList.clearSelection()
	def log(self, text):
		self.ui.outputText.append(' * ' + QtCore.QTime.currentTime().toString() + ': ' + text)
	def getConfigByAlias(self, alias):
		for config in self.compConfig:
			if config.alias == alias:
				return config
		return None
	#
	# Return 1 if docking is selected, 0 otherwise.
	def wantsDocking(self):
		if self.doDock == True: return 1
		else: return 0
	def resizeEvent(self, e):
		old = e.oldSize()
		new = e.size()
		inc = new - old
		if (inc.width != 0 or inc.height!=0):
			self.canvas.resize(self.canvas.size()+inc)
		e.accept()