Пример #1
0
Файл: gui.py Проект: sammdot/S3
class GuiClient(QApplication):

	def __init__(self, config):
		self.config = conf = {
			"width": 960,
			"height": 600,
			"font": "default",
			"fontsize": 10,
			"consolebg": "black",
			"consolefg": "white",
			"consoleheight": 150,
			"qtargs": [],
		}
		conf.update(config)

		self.client = None
		self.server_name = None
		self.loop = QEventLoop(self)
		asyncio.set_event_loop(self.loop)

		self.network = None
		self.network_layout = None

		QApplication.__init__(self, conf["qtargs"])

		self.frame = QMainWindow()
		self.frame.setFixedSize(conf["width"], conf["height"])
		self.create_menu()

		self._widget = QWidget()
		self._layout = QVBoxLayout(self._widget)
		self._widget.setLayout(self._layout)
		self.frame.setCentralWidget(self._widget)

		self.layout = MainLayoutPanel(self.frame)
		self._layout.addWidget(self.layout, 1)

		self.console = ConsolePanel(self.frame, conf["consoleheight"],
			conf["consolebg"], conf["consolefg"],
			conf["font"], conf["fontsize"])
		self._layout.addWidget(self.console)

		self.aboutToQuit.connect(self.stop)

	def start(self):
		self.frame.show()
		self.exec_()

	def stop(self):
		# TODO: check if the user wants to leave,
		# if still connected to a server.

		for win in self.layout.sub_windows:
			win.close()

		self.loop.call_soon_threadsafe(self.loop.close)
		self.quit()

	def create_menu(self):
		def _create_connect_function(name, addr):
			return lambda: self._connect_to_server(name, *addr)

		menus = [
			# TODO: menu items
			("&Server", [
				("&Quit", self.stop)
			]),
			("&Bookmarks", [
				(name, _create_connect_function(name, value["address"]))
				for name, value in sorted(self.config["bookmarks"].items())
			])
		]

		menubar = self.frame.menuBar()

		for name, items in menus:
			submenu = menubar.addMenu(name)
			for label, function in items:
				if label is None:
					submenu.addSeparator()
				else:
					action = QAction(label, submenu)
					submenu.addAction(action)
					action.triggered.connect(function)

	def _connect_to_server(self, name, host, port):
		"""
		Create a new client instance to connect
		to the specified hostname and port.
		"""
		if self.client is not None:
			self.client.stop()
			self.client = None
			self.server_name = None

		async def connect():
			try:
				self.client = Client(host, port) # TODO: SSL
				self.client.add_observer(self._on_receive_message)
				self.server_name = name
				await self.client.start()
				# TODO: handle disconnection
			except ClientError as e:
				print("Cannot connect to {0}:{1}: {2}".format(host, port, e.args), file=self.console)

		asyncio.ensure_future(connect())

	def _on_receive_message(self, msg):
		bookmark_config = self.config["bookmarks"][self.server_name]

		if msg.command == "001":
			if "mode" in bookmark_config:
				self.client.send(Message("MODE", bookmark_config["mode"]))
			else:
				# TODO: let user select session mode
				print("Session mode required", file=self.console)

		elif msg.command == "002":
			print("Connected to {0}:{1}".format(self.client.host, self.client.port), file=self.console)

		elif msg.command == "003":
			if "login" in bookmark_config:
				self.client.send(Message("LOGIN", *bookmark_config["login"]))
			else:
				# TODO: let user login
				print("Login required", file=self.console)

		elif msg.command == "010":
			async def download_network():
				cli = DownloadClient(self.client.host, msg.params[0])
				par = Reader(await cli.download(), "<download>")
				self.network = par.create_network()

			async def download_layout():
				cli = DownloadClient(self.client.host, msg.params[1])
				par = LayoutReader(self.network, await cli.download(), "<download>")
				self.network_layout = par.create_layouts()

			async def download_all():
				await download_network()
				await download_layout()
				print("Downloaded interlocking data", file=self.console)
				self.client.send(Message("DLACK"))
				await self.layout.draw(self.network, self.network_layout,
					self.network_layout["_viewport"], 5) # TODO: arbitrary scale

			asyncio.ensure_future(download_all())

		elif msg.command == "011":
			pass

		elif msg.command == "TRACK":
			state, section = msg.params
			track = self.network.track_section(section)
			track.occupied = state == "R"

		else:
			# TODO
			print(msg, file=self.console)

		self.layout.layout.update()
		for win in self.layout.sub_windows:
			win.layout.update()