Exemplo n.º 1
0
class Window(QDialog):

	Move			 = 0b0000
	ResizeTop		 = 0b0001
	ResizeRight		 = 0b0010
	ResizeBottom	 = 0b0100
	ResizeLeft		 = 0b1000

	onshow			 = pyqtSignal()
	onhide			 = pyqtSignal()
	onfocus			 = pyqtSignal()
	onblur			 = pyqtSignal()
	onclose			 = pyqtSignal()
	onmove			 = pyqtSignal(int, int, int, int)
	onresize		 = pyqtSignal(int, int, int, int)
	onstatechange	 = pyqtSignal()
	onmouseenter	 = pyqtSignal()
	onmouseleave	 = pyqtSignal()

	def __init__(self, parent = None, url = '', width = None, height = None, isDialog = False):
		super(Window, self).__init__(parent if isDialog else None)
		assets.windows.append(self)
		if width is None:
			width = assets.manifest['width']
		if height is None:
			height = assets.manifest['height']
		windowFlags = Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint
		if isDialog:
			windowFlags |= Qt.Dialog
		else:
			windowFlags |= Qt.CustomizeWindowHint
		self.dragParams = {'type': 0, 'x': 0, 'y': 0, 'size': 5, 'margin': 0, 'draging': False}
		self.webView = WebView(self, url)
		self.api = API(self)
		self.parent = parent
		self.resize(width, height)
		self.setMouseTracking(True)
		self.setWindowFlags(windowFlags)
		self.setWindowTitle('Hybrid App Engine')
		self.setAttribute(Qt.WA_QuitOnClose, True)
		self.setAttribute(Qt.WA_DeleteOnClose, True)
		self.setAttribute(Qt.WA_TranslucentBackground, True)
		self.setVisible(assets.manifest['visible'])
		self.setResizable(assets.manifest['resizable'])
		self.setFrameless(assets.manifest['frameless'])
		self.setWindowIcon(QIcon(assets.manifest['icon']))
		self.setTransBackground(assets.manifest['transBackground'])

	# Methods

	def setWindowFlags(self, windowFlags):
		visible = self.isVisible()
		super(Window, self).setWindowFlags(windowFlags)
		if visible:
			self.show()

	def testWindowFlags(self, windowFlags):
		return self.windowFlags() & windowFlags

	def getCursorType(self, x, y):
		width = self.width()
		height = self.height()
		size = self.dragParams['size']
		margin = self.dragParams['margin']
		isResizableX = self.isResizableX()
		isResizableY = self.isResizableY()
		cursorType = Window.Move
		if x >= margin and x <= width - margin and y >= margin and y <= height - margin:
			if y <= size + margin and isResizableY:
				cursorType |= Window.ResizeTop
			elif y >= height - margin - size and isResizableY:
				cursorType |= Window.ResizeBottom
			if x <= size + margin and isResizableX:
				cursorType |= Window.ResizeLeft
			elif x >= width - margin - size and isResizableX:
				cursorType |= Window.ResizeRight
		return cursorType

	# Slots

	# 获取父窗口
	@pyqtSlot(result = QObject)
	def opener(self):
		return self.parent

	# 任务栏闪烁
	@pyqtSlot()
	@pyqtSlot(int)
	def alert(self, msec = 0):
		QApplication.alert(self, msec)

	# 执行简单的JS
	@pyqtSlot(str, result = QObject)
	def eval(self, javaScript):
		obj = QObject(self)
		obj.setObjectName('evalResult')
		obj.setProperty('result', self.webView.eval(javaScript))
		print(dir(self.onstatechange))
		return obj

	# 截图
	@pyqtSlot(result = str)
	@pyqtSlot(bool, result = str)
	@pyqtSlot(bool, str, result = bool)
	def capture(self, fullScreen = False, filename = ''):
		if fullScreen:
			image = QApplication.primaryScreen().grabWindow(0)
		else:
			image = QImage(self.webView.mainFrame.contentsSize(), QImage.Format_ARGB32)
			painter = QPainter(image)
			self.webView.mainFrame.render(painter)
			painter.end()
		if filename:
			return image.save(filename)
		else:
			data = QByteArray()
			buffer = QBuffer(data)
			buffer.open(QBuffer.WriteOnly)
			image.save(buffer, 'PNG')
			return bytes(data.toBase64()).decode()

	# 打开开发者工具
	@pyqtSlot()
	def showInspector(self):
		self.webView.page().showInspector()

	# 关闭开发者工具
	@pyqtSlot()
	def hideInspector(self):
		self.webView.page().hideInspector()

	# 搜索文本
	@pyqtSlot(str, result = bool)
	def findText(self, text):
		return self.webView.page().findText(text)

	# 设置窗口图标
	@pyqtSlot(str)
	def setIcon(self, icon):
		if isinstance(icon, str):
			icon = QIcon(self.api.normUrl(icon))
		self.setWindowIcon(icon)

	# 设置内容是否已被修改(标题中需要有[*]标志)
	@pyqtSlot(bool)
	def setModified(self, modified):
		self.setWindowModified(modified)

	# 获取内容是否已被修改
	@pyqtSlot(result = bool)
	def isModified(self):
		return self.isWindowModified()

	# 设置是否模态
	@pyqtSlot(bool)
	def setModal(self, modal):
		super(Window, self).setModal(modal)

	# 获取是否模态
	@pyqtSlot(result = bool)
	def isModal(self):
		return super(Window, self).isModal()

	# 设置是否在任务栏中显示
	@pyqtSlot(bool)
	def setShowInTaskbar(self, showInTaskbar):
		if showInTaskbar:
			self.setWindowFlags(self.windowFlags() & ~ Qt.Tool)
		else:
			self.setWindowFlags(self.windowFlags() | Qt.Tool)

	# 获取是否在任务栏中显示
	@pyqtSlot(result = bool)
	def isShowInTaskbar(self):
		return self.testWindowFlags(Qt.Tool)

	# 设置窗口是否置顶
	@pyqtSlot(bool)
	def setStaysOnTop(self, staysOnTop):
		if staysOnTop:
			self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.WindowStaysOnTopHint)

	# 获取窗口是否置顶
	@pyqtSlot(result = bool)
	def isStaysOnTop(self):
		return self.testWindowFlags(Qt.WindowStaysOnTopHint)

	# 设置是否显示系统边框
	@pyqtSlot(bool)
	def setFrameless(self, frameless):
		if frameless:
			self.setWindowFlags(self.windowFlags() & ~ Qt.CustomizeWindowHint & ~ Qt.WindowTitleHint | Qt.FramelessWindowHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.FramelessWindowHint | Qt.CustomizeWindowHint | Qt.WindowTitleHint)

	# 获取是否显示系统边框
	@pyqtSlot(result = bool)
	def isFrameless(self):
		return self.testWindowFlags(Qt.FramelessWindowHint)

	# 设置是否背景透明
	@pyqtSlot(bool)
	def setTransBackground(self, transBackground):
		palette = self.palette()
		if transBackground:
			palette.setBrush(QPalette.Base, Qt.transparent)
		else:
			palette.setBrush(QPalette.Base, Qt.white)
		self.setPalette(palette)

	# 获取是否背景透明
	@pyqtSlot(result = bool)
	def isTransBackground(self):
		palette = self.palette()
		return palette.brush(QPalette.Base) == Qt.transparent

	# 设置是否鼠标事件穿透
	@pyqtSlot(bool)
	def setTransMouseEvent(self, transMouseEvent):
		self.setAttribute(Qt.WA_TransparentForMouseEvents, transMouseEvent)
		self.setWindowFlags(self.windowFlags() | Qt.WindowTitleHint)

	# 获取是否是否鼠标事件穿透
	@pyqtSlot(result = bool)
	def isTransMouseEvent(self):
		return self.testAttribute(Qt.WA_TransparentForMouseEvents)

	# 设置窗口不透明度
	@pyqtSlot(float)
	def setOpacity(self, opacity):
		self.setWindowOpacity(opacity)

	# 获取窗口不透明度
	@pyqtSlot(result = float)
	def getOpacity(self):
		return self.windowOpacity()

	# 设置尺寸是否可调整
	@pyqtSlot(bool)
	def setResizable(self, resizable):
		if resizable:
			self.setMinimumSize(5, 5)
			self.setMaximumSize(0xFFFFFF, 0xFFFFFF)
		else:
			self.setFixedSize(self.width(), self.height())

	# 获取尺寸是否可调整
	@pyqtSlot(result = bool)
	def isResizable(self):
		return self.minimumSize() != self.maximumSize()

	# 设置宽度是否可调整
	@pyqtSlot(bool)
	def setResizableX(self, resizableX):
		if resizableX:
			self.setMinimumWidth(5)
			self.setMaximumWidth(0xFFFFFF)
		else:
			self.setFixedWidth(self.width())

	# 获取宽度是否可调整
	@pyqtSlot(result = bool)
	def isResizableX(self):
		return self.minimumWidth() != self.maximumWidth()

	# 设置高度是否可调整
	@pyqtSlot(bool)
	def setResizableY(self, resizableY):
		if resizableY:
			self.setMinimumHeight(5)
			self.setMaximumHeight(0xFFFFFF)
		else:
			self.setFixedHeight(self.height())

	# 获取高度是否可调整
	@pyqtSlot(result = bool)
	def isResizableY(self):
		return self.minimumHeight() != self.maximumHeight()

	# 设置是否可最小化
	@pyqtSlot(bool)
	def setMinimizable(self, minimizable):
		if minimizable:
			self.setWindowFlags(self.windowFlags() | Qt.WindowMinimizeButtonHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.WindowMinimizeButtonHint)

	# 获取是否可最小化
	@pyqtSlot(result = bool)
	def isMinimizable(self):
		return self.testWindowFlags(Qt.WindowMinimizeButtonHint)

	# 设置是否可最大化
	@pyqtSlot(bool)
	def setMaximizable(self, maximizable):
		if maximizable:
			self.setWindowFlags(self.windowFlags() | Qt.WindowMaximizeButtonHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.WindowMaximizeButtonHint)

	# 获取是否可最大化
	@pyqtSlot(result = bool)
	def isMaximizable(self):
		return self.testWindowFlags(Qt.WindowMaximizeButtonHint)

	# 设置是否可关闭
	@pyqtSlot(bool)
	def setClosable(self, closable):
		if closable:
			self.setWindowFlags(self.windowFlags() | Qt.WindowCloseButtonHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.WindowCloseButtonHint)

	# 获取是否可关闭
	@pyqtSlot(result = bool)
	def isClosable(self):
		return self.testWindowFlags(Qt.WindowCloseButtonHint)

	# 获取是否已最小化
	@pyqtSlot(result = bool)
	def isMinimized(self):
		return super(Window, self).isMinimized()

	# 获取是否已最大化
	@pyqtSlot(result = bool)
	def isMaximized(self):
		return super(Window, self).isMaximized()

	# 获取是否已最大化
	@pyqtSlot(result = bool)
	def isFullScreen(self):
		return super(Window, self).isFullScreen()

	# 最小化
	@pyqtSlot()
	def minimize(self):
		if self.isMinimizable():
			self.showMinimized()

	# 还原
	@pyqtSlot()
	def normalize(self):
		self.showNormal()

	# 最大化
	@pyqtSlot()
	def maximize(self):
		if self.isMaximizable():
			self.showMaximized()

	# 全屏
	@pyqtSlot()
	def showFullScreen(self):
		super(Window, self).showFullScreen()

	# 设置窗口坐标
	@pyqtSlot(int, int)
	def setPos(self, x, y):
		self.move(x, y)

	# 设置窗口尺寸
	@pyqtSlot(int, int)
	def setSize(self, width, height):
		self.resize(width, height)

	# 设置窗口最小尺寸
	@pyqtSlot(int, int)
	def setMinSize(self, width, height):
		self.setMinimumSize(width, height)

	# 设置窗口最大尺寸
	@pyqtSlot(int, int)
	def setMaxSize(self, width, height):
		self.setMaximumSize(width, height)

	# 设置尺寸控制大小
	@pyqtSlot(int)
	def setResizerSize(self, size):
		self.dragParams['size'] = size

	# 获取尺寸控制大小
	@pyqtSlot(result = int)
	def getResizerSize(self):
		return self.dragParams['size']

	# 设置尺寸控制边距
	@pyqtSlot(int)
	def setResizerMargin(self, margin):
		self.dragParams['margin'] = margin

	# 获取尺寸控制边距
	@pyqtSlot(result = int)
	def getResizerMargin(self):
		return self.dragParams['margin']

	# 是否正在拖动
	@pyqtSlot(result = bool)
	def isDraging(self):
		return self.dragParams['draging']

	# 开始拖动
	@pyqtSlot()
	def dragStart(self):
		self.dragParams['draging'] = True

	# 结束拖动
	@pyqtSlot()
	def dragStop(self):
		self.dragParams['type'] = Window.Move
		self.dragParams['draging'] = False

	# 窗口获取焦点
	@pyqtSlot()
	def activate(self):
		self.activateWindow()

	# 窗口是否已获得焦点
	@pyqtSlot(result = bool)
	def isActive(self):
		return self.isActiveWindow()

	# 设置窗口可用状态
	@pyqtSlot(bool)
	def setEnabled(self, enabled):
		super(Window, self).setEnabled(enabled)

	# 窗口是否可用
	@pyqtSlot(result = bool)
	def isEnabled(self):
		return super(Window, self).isEnabled()

	# 设置窗口可见状态
	@pyqtSlot(result = bool)
	def setVisible(self, visible):
		super(Window, self).setVisible(visible)

	# 窗口是否显示
	@pyqtSlot(result = bool)
	def isVisible(self):
		return super(Window, self).isVisible()

	# 显示窗口
	@pyqtSlot()
	def show(self):
		super(Window, self).show()

	# 隐藏窗口
	@pyqtSlot()
	def hide(self):
		super(Window, self).hide()

	# 关闭窗口
	@pyqtSlot()
	def close(self):
		super(Window, self).close()

	# Events
	def keyPressEvent(self, event):
		if(event.key() == Qt.Key_Escape):
			event.ignore()

	def mousePressEvent(self, event):
		self.dragParams['x'] = event.x()
		self.dragParams['y'] = event.y()
		self.dragParams['globalX'] = event.globalX()
		self.dragParams['globalY'] = event.globalY()
		self.dragParams['width'] = self.width()
		self.dragParams['height'] = self.height()
		if self.dragParams['type'] != Window.Move and self.isFrameless() and not self.isMaximized() and not self.isFullScreen():
			self.dragStart()

	def mouseReleaseEvent(self, event):
		self.dragStop()

	def mouseMoveEvent(self, event):

		if self.isFrameless() and not self.isMaximized() and not self.isFullScreen():
			# 判断鼠标类型
			cursorType = self.dragParams['type']
			if not self.dragParams['draging']:
				cursorType = self.dragParams['type'] = self.getCursorType(event.x(), event.y())

			# 设置鼠标形状
			if cursorType in (Window.ResizeTop, Window.ResizeBottom):
				self.webView.setCursor(Qt.SizeVerCursor)
			elif cursorType in (Window.ResizeLeft, Window.ResizeRight):
				self.webView.setCursor(Qt.SizeHorCursor)
			elif cursorType in (Window.ResizeTop | Window.ResizeRight, Window.ResizeLeft | Window.ResizeBottom):
				self.webView.setCursor(Qt.SizeBDiagCursor)
			elif cursorType in (Window.ResizeTop | Window.ResizeLeft, Window.ResizeRight | Window.ResizeBottom):
				self.webView.setCursor(Qt.SizeFDiagCursor)
			elif self.dragParams['draging']:
				self.webView.setCursor(Qt.ArrowCursor)

		# 判断窗口拖动
		dragType = self.dragParams['type']
		if self.dragParams['draging'] and not self.isMaximized() and not self.isFullScreen():
			x = self.x()
			y = self.y()
			width = self.width()
			height = self.height()
			if dragType == Window.Move:
				x = event.globalX() - self.dragParams['x']
				y = event.globalY() - self.dragParams['y']
			elif self.isFrameless():
				if dragType & Window.ResizeTop == Window.ResizeTop:
					y = event.globalY() - self.dragParams['margin']
					height = self.dragParams['height'] + self.dragParams['globalY'] - event.globalY()
				elif dragType & Window.ResizeBottom == Window.ResizeBottom:
					height = self.dragParams['height'] - self.dragParams['globalY'] + event.globalY()
				if dragType & Window.ResizeLeft == Window.ResizeLeft:
					x = event.globalX() - self.dragParams['margin']
					width = self.dragParams['width'] + self.dragParams['globalX'] - event.globalX()
				elif dragType & Window.ResizeRight == Window.ResizeRight:
					width = self.dragParams['width'] - self.dragParams['globalX'] + event.globalX()
			else:
				return

			if width < self.minimumWidth():
				width = self.minimumWidth()
			elif width > self.maximumWidth():
				width = self.maximumWidth()
			if height < self.minimumHeight():
				height = self.minimumHeight()
			elif height > self.maximumHeight():
				height = self.maximumHeight()

			self.setGeometry(x, y, width, height)

	def changeEvent(self, event):
		if event.type() == QEvent.ActivationChange:
			if self.isActiveWindow():
				self.onfocus.emit()
			else:
				self.onblur.emit()
		elif event.type() == QEvent.WindowStateChange:
			self.onstatechange.emit()

	def resizeEvent(self, event):
		size = event.size()
		oldSize = event.oldSize()
		self.onresize.emit(size.width(), size.height(), oldSize.width(), oldSize.height())
		self.webView.resize(super(Window, self).size())

	def moveEvent(self, event):
		pos = event.pos()
		oldPos = event.oldPos()
		self.onmove.emit(pos.x(), pos.y(), oldPos.x(), oldPos.y())

	def enterEvent(self, event):
		self.onmouseenter.emit()

	def leaveEvent(self, event):
		self.onmouseleave.emit()

	def showEvent(self, event):
		self.onshow.emit()

	def hideEvent(self, event):
		self.onhide.emit()

	def closeEvent(self, event):
		self.onclose.emit()
		if self.isClosable():
			self.webView.close()
			assets.windows = [i for i in assets.windows if i != self]
			event.accept()
		else:
			event.ignore()