From 29a7dc2a4a3d48b8a1db4adeed4375b75c71933b Mon Sep 17 00:00:00 2001 From: Srevin Saju Date: Wed, 22 Jul 2020 00:38:15 +0300 Subject: [PATCH] Update version --- guiscrcpy.desktop | 2 +- guiscrcpy/launcher.py | 49 ++- guiscrcpy/lib/mapper/ux.py | 166 ++++++++ guiscrcpy/ui/ui/guiscrcpy_logo.svg | 636 +++++++++++++++-------------- guiscrcpy/version.py | 3 +- releaser | 4 +- setup.py | 6 +- 7 files changed, 548 insertions(+), 318 deletions(-) diff --git a/guiscrcpy.desktop b/guiscrcpy.desktop index efbbcf74..ee816e4a 100644 --- a/guiscrcpy.desktop +++ b/guiscrcpy.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -Version=4.0.alpha1 +Version=4.0.a3 Name=guiscrcpy GenericName=guiscrcpy Comment=Open Source Android Screen Mirroring System diff --git a/guiscrcpy/launcher.py b/guiscrcpy/launcher.py index fb805d94..e87cb743 100644 --- a/guiscrcpy/launcher.py +++ b/guiscrcpy/launcher.py @@ -35,6 +35,7 @@ import hashlib import logging import os +import subprocess import sys import time import webbrowser @@ -347,10 +348,31 @@ sys.exit(1) if args.mapper: - from guiscrcpy.lib import mapper + if not args.mapper_device_id: + print("Please pass the --mapper-device-id to initialize " + "the mapper") + sys.exit(1) + from guiscrcpy.lib.mapper.mapper import Mapper # Initialize the mapper if it is called. print('Initializing guiscrcpy mapper v3.5-') - mapper.file_check() + mp = Mapper(args.mapper_device_id) + if not os.path.exists( + os.path.join(cfgmgr.get_cfgpath(), 'guiscrcpy.mapper.json')): + print("guiscrcpy.mapper.json does not exist. ") + print("Initializing Mapper Configuration for the first time use.") + mp.initialize(initialize_qt=True) + print("Keys registered.") + print('Please run this command again to listen to map keys') + else: + print("guiscrcpy.mapper.json found. Starting the mapper...") + print("Your keyboard is being listened by guiscrcpy-mapper") + print("pressing any key will trigger the position.") + print() + print('If you would like to register new keys, pass --mapper-reset') + print("\nInitializing\n\n") + mp.listen_keypress() + print("Done!") + sys.exit(0) logger.debug("Importing modules...") @@ -518,10 +540,13 @@ def network_mgr(self): self.nm.show() def bootstrap_mapper(self): + if (os.path.exists( os.path.join(cfgmgr.get_cfgpath() + "guiscrcpy.mapper.json"))): - from guiscrcpy.lib import mapper - mapper.file_check() + from guiscrcpy.lib.mapper.mapper import MapperAsync + _, identifier = self.current_device_identifier() + self.mp = MapperAsync(self, identifier, initialize=False) + self.mp.start() self.private_message_box_adb.setText( "guiscrcpy-mapper has started" ) @@ -529,14 +554,16 @@ def bootstrap_mapper(self): message_box = QMessageBox() message_box.setText( "guiscrcpy mapper is not initialized yet." - "Would you like to initialize it now? " + "Please initialize guiscrcpy by running : " + "'guiscrcpy --mapper' on the command line" ) message_box.setInformativeText( "Before you initialize, make sure your phone is connected and " "the display is switched on to map the points." ) - message_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) + message_box.setStandardButtons(QMessageBox.Ok) user_message_box_response = message_box.exec() + return if user_message_box_response == QMessageBox.Ok: self.private_message_box_adb.setText( "Initializing mapper in 5 seconds") @@ -554,7 +581,8 @@ def bootstrap_mapper(self): "reset, reset and reset again! :D" ) print() - mapper.file_check() + _, identifier = self.current_device_identifier() + @staticmethod def launch_usb_audio(): @@ -606,12 +634,15 @@ def reset(self): message_box.addButton("OK", self.quit_window) message_box.show() - @staticmethod - def quit_window(): + def quit_window(self): """ A method to quit the main window :return: """ + try: + self.mp.exit() + except (AttributeError, KeyboardInterrupt): + pass sys.exit() def forget_paired_device(self): diff --git a/guiscrcpy/lib/mapper/ux.py b/guiscrcpy/lib/mapper/ux.py index e69de29b..861a34f5 100644 --- a/guiscrcpy/lib/mapper/ux.py +++ b/guiscrcpy/lib/mapper/ux.py @@ -0,0 +1,166 @@ +import json +import uuid +import time + +from qtpy import QtGui, QtCore, QtWidgets +from qtpy.QtCore import Qt, QThread +from qtpy.QtGui import QPixmap +from guiscrcpy.lib.check import adb + + +class MapperUI(QtWidgets.QWidget): + """ + Guiscrcpy Mapper User Interface + configuration an button + mapping + """ + def __init__(self, core, screenshot_path, dimensions, + fixed_pos=[0.0, 0.0], final_pos=[0.0, 0.0]): + self.fixed_pos = fixed_pos + self.final_pos = final_pos + self.core = core + self.last_found_point = None + self.image = None + QtWidgets.QWidget.__init__(self) + self.build_user_interface() + self.screenshot_path = screenshot_path + self.dimensions = dimensions + self.set_screenshot_to_label(self.screenshot_path) + + def build_user_interface(self): + self.label = QtWidgets.QLabel(self) + self.drawing = False + self.widget = QtWidgets.QWidget(self) + self.widget.setGeometry(QtCore.QRect(0, 0, 351, 34)) + self.widget.setObjectName("widget") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget) + self.horizontalLayout.setSizeConstraint( + QtWidgets.QLayout.SetMaximumSize) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.lineEdit = QtWidgets.QLineEdit(self.widget) + size_policy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + size_policy.setHorizontalStretch(0) + size_policy.setVerticalStretch(0) + size_policy.setHeightForWidth( + self.lineEdit.sizePolicy().hasHeightForWidth()) + self.lineEdit.setSizePolicy(size_policy) + self.lineEdit.setMinimumSize(QtCore.QSize(25, 25)) + self.lineEdit.setMaximumSize(QtCore.QSize(25, 16777215)) + self.lineEdit.setMaxLength(1) + self.lineEdit.setObjectName("lineEdit") + self.horizontalLayout.addWidget(self.lineEdit) + self.pushButton = QtWidgets.QPushButton(self.widget) + self.pushButton.setMaximumSize(QtCore.QSize(50, 16777215)) + self.pushButton.setObjectName("pushButton") + self.horizontalLayout.addWidget(self.pushButton) + self.label0 = QtWidgets.QLabel(self.widget) + self.label0.setMinimumSize(QtCore.QSize(25, 25)) + self.label0.setStyleSheet( + "color: rgb(0, 0, 0);\n" + "border-radius: 10px;\n" + "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, " + "y2:1, stop:0 rgba(61, 255, 0, 255), stop:1 rgba(226, 255, 0, " + "255));\n " + ) + self.label0.setAlignment(QtCore.Qt.AlignCenter) + self.label0.setObjectName("label") + self.horizontalLayout.addWidget(self.label0) + self.pushButton.pressed.connect(self.register_key) + self.label.setSizePolicy( + QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored + ) + self.label.resize(800, 600) + self.setContentsMargins(0, 0, 0, 0) + self.label.setContentsMargins(0, 0, 0, 0) + + def set_screenshot_to_label(self, screenshot_path): + """ + Sets the pixmap of a QLabel to the path provided by the screenshot path + :param screenshot_path: the full path to the screenshot file (*.png) + :type screenshot_path: str + :return: None + :rtype: None + """ + self.pixmap = QtGui.QPixmap(screenshot_path) + self.label.resize( + int(0.5 * self.pixmap.width()), + int(0.5 * self.pixmap.height()) + ) + self.resize( + int(0.5 * self.pixmap.width()), + int(0.5 * self.pixmap.height()) + ) + + self.show() + self.resize(self.label.size()) + self.label.setPixmap(self.pixmap) + self.label.setMinimumSize(1, 1) + self.label.setMaximumSize( + int(0.5 * self.pixmap.width()), int(0.5 * self.pixmap.height()) + ) + self.setMaximumSize( + int(0.5 * self.pixmap.width()), + int(0.5 * self.pixmap.height()) + ) + self.label.installEventFilter(self) + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(self.label) + self.pushButton.setText("OK") + self.label0.setWordWrap(True) + self.label0.setText( + "Click the point, and enter char in textbox and " + "press OK to continue." + ) + + def register_key(self): + relx = self.fixed_pos[0] / self.label.width() + rely = self.fixed_pos[1] / self.label.height() + fixx = relx * int(self.dimensions[0]) + fixy = rely * int(self.dimensions[1]) + char = self.lineEdit.text()[:1] + print("Successfully registered {ch} " + "with position ({x}, {y})".format(ch=char, x=fixx, y=fixy)) + self.core.add_position(char, (fixx, fixy)) + self.label0.setText( + "SUCCESS! " + "Add a new point and enter char; " + "close the window to finish adding." + ) + + def eventFilter(self, source, event): + if source is self.label and event.type() == QtCore.QEvent.Resize: + self.label.setPixmap( + self.pixmap.scaled(self.label.size(), + QtCore.Qt.KeepAspectRatio) + ) + return super(MapperUI, self).eventFilter(source, event) + + def mousePressEvent(self, event): + if event.button() == Qt.LeftButton: + self.last_found_point = event.pos() + self.fixed_pos[0] = int(event.pos().x()) + self.fixed_pos[1] = int(event.pos().y()) + print(self.last_found_point, "LAST") + self.last_found_point = self.label.mapFromParent( + event.pos()) # this is working fine now + # self.label.setPixmap(QPixmap.fromImage(self.image)) + + def mouseMoveEvent(self, event): + if event.buttons() & Qt.LeftButton: + # painter.setPen(QPen(self.brushColor, + # self.brushSize, Qt.SolidLine, Qt.RoundCap,Qt.RoundJoin)) + # painter.drawLine( + # self.label.mapFromParent(event.pos()),self.last_found_point) + self.last_found_point = self.label.mapFromParent( + event.pos()) # this is working fine now + print(self.last_found_point, "MOVE") + self.fixed_pos[0] = int(event.pos().x()) + self.fixed_pos[1] = int(event.pos().y()) + # self.label.setPixmap(QPixmap.fromImage(self.image)) + + def mouseReleaseEvent(self, event): + if event.button == Qt.LeftButton: + # self.drawing = False + self.label.setPixmap(QPixmap.fromImage(self.image)) diff --git a/guiscrcpy/ui/ui/guiscrcpy_logo.svg b/guiscrcpy/ui/ui/guiscrcpy_logo.svg index 9cf24649..8050a996 100644 --- a/guiscrcpy/ui/ui/guiscrcpy_logo.svg +++ b/guiscrcpy/ui/ui/guiscrcpy_logo.svg @@ -1,6 +1,4 @@ - - + inkscape:export-filename="/media/ss/WD-SS1/Srevin/Python/guiscrcpy/ui/guiscrcpy_logo.png" + sodipodi:docname="guiscrcpy_logo.svg" + inkscape:version="1.0 (4035a4fb49, 2020-05-01)" + id="svg8" + version="1.1" + viewBox="0 0 132.29167 132.29167" + height="132.29167mm" + width="132.29167mm"> + id="linearGradient2207" + inkscape:collect="always"> + style="stop-color:#0f00f9;stop-opacity:1" /> + style="stop-color:#ff00f5;stop-opacity:1" /> + id="linearGradient1593" + inkscape:collect="always"> + style="stop-color:#00f977;stop-opacity:1" /> + style="stop-color:#00ffe3;stop-opacity:1" /> + inkscape:collect="always" + id="linearGradient1526"> + id="stop1522" /> + id="stop1524" /> + inkscape:collect="always" + id="linearGradient1520"> + id="stop1516" /> + id="stop1518" /> + id="linearGradient1514" + inkscape:collect="always"> + style="stop-color:#f96900;stop-opacity:1" /> + style="stop-color:#f0ff00;stop-opacity:1" /> + inkscape:collect="always" + id="linearGradient1304"> + id="stop1300" /> + id="stop1302" /> + id="Arrow1Lstart" + refX="0.0" + refY="0.0" + orient="auto" + inkscape:stockid="Arrow1Lstart"> + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + id="path1018" /> + id="linearGradient1014" + inkscape:collect="always"> + style="stop-color:#0f00f9;stop-opacity:1" /> + style="stop-color:#611fe0;stop-opacity:1" /> + inkscape:collect="always" + id="linearGradient1008"> + id="stop1004" /> + id="stop1006" /> + id="clipPath943" + clipPathUnits="userSpaceOnUse"> + id="path945" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccscccsscccsssccccsccscccccsccsccscscscccsccccscccccscccccssssscccccscccscc" /> + x2="122.32238" + y1="138.16405" + x1="83.507729" + id="linearGradient990" + xlink:href="#linearGradient2207" + inkscape:collect="always" /> + x2="52.462818" + y1="135.73422" + x1="146.79344" + id="linearGradient1002" + xlink:href="#linearGradient1593" + inkscape:collect="always" /> + y2="101.20832" + x2="167.2556" + y1="101.20832" + x1="39.119401" + id="linearGradient1016" + xlink:href="#linearGradient1014" + inkscape:collect="always" /> + id="clipPath1378" + clipPathUnits="userSpaceOnUse"> + cx="103.1875" + id="circle1380" + style="fill:url(#linearGradient1382);fill-opacity:1;stroke:none;stroke-width:0.85822999;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - + id="linearGradient1382" + xlink:href="#linearGradient1008" + inkscape:collect="always" /> - + y2="118.05499" + x2="72.433861" + y1="86.093674" + x1="62.771938" + id="linearGradient1408" + xlink:href="#linearGradient1514" + inkscape:collect="always" /> - + id="linearGradient1433" + xlink:href="#linearGradient1526" + inkscape:collect="always" /> + + + + y1="89.491074" + x1="84.315445" + gradientTransform="matrix(1.3236379,0,0,1.3236379,-23.242211,-33.366492)" + gradientUnits="userSpaceOnUse" + id="linearGradient1483-2" + xlink:href="#linearGradient1304" + inkscape:collect="always" /> + inkscape:window-height="1054" + inkscape:window-width="1920" + inkscape:snap-global="false" + showgrid="false" + inkscape:current-layer="g1544" + inkscape:document-units="mm" + inkscape:cy="302.91139" + inkscape:cx="-501.24431" + inkscape:zoom="0.35" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" /> @@ -282,159 +281,192 @@ + inkscape:groupmode="layer" + inkscape:label="Layer 1"> + clip-path="url(#clipPath1378)" + id="g1341" /> + transform="matrix(1.0619183,0,0,1.0619183,-6.3891948,-6.2666475)" + id="g1544"> + cx="103.1875" + cy="101.20832" + r="56.768341" /> - - + + + id="path1400-6" + sodipodi:sides="6" + sodipodi:cx="71.815475" + sodipodi:cy="103.09821" + sodipodi:r1="24.495451" + sodipodi:r2="12.247726" + sodipodi:arg1="-0.036128851" + sodipodi:arg2="0.48746993" + inkscape:flatsided="true" + inkscape:rounded="0" + inkscape:randomized="0" + d="m 96.294941,102.21341 -11.473473,21.64224 -24.479466,0.8848 -13.005992,-20.75744 11.473473,-21.642236 24.479466,-0.8848 z" + transform="matrix(0.41527817,0.20609039,-0.20609039,0.41527817,120.4235,52.569806)" /> + width="47.550892" + height="89.430588" + x="78.763283" + y="57.920357" + ry="2.9321504" /> + width="42.556416" + height="71.447929" + x="81.369576" + y="67.427773" + ry="2.342555" /> + width="49.586258" + height="83.250328" + x="77.765495" + y="61.847599" + ry="2.7295189" + clip-path="url(#clipPath943)" + transform="matrix(0.85823,0,0,0.85823,14.628891,14.348304)" /> + cx="103.1875" + cy="101.20832" + r="58.857162" /> - - + + + id="path1400-6-9-3-2" + sodipodi:sides="6" + sodipodi:cx="71.815475" + sodipodi:cy="103.09821" + sodipodi:r1="24.495451" + sodipodi:r2="12.247726" + sodipodi:arg1="-0.036128851" + sodipodi:arg2="0.48746993" + inkscape:flatsided="true" + inkscape:rounded="0" + inkscape:randomized="0" + d="m 96.294941,102.21341 -11.473473,21.64224 -24.479466,0.8848 -13.005992,-20.75744 11.473473,-21.642236 24.479466,-0.8848 z" + transform="matrix(0.20057447,0.16637432,-0.16557296,0.20393445,67.125647,83.644693)" + inkscape:transform-center-y="17.894833" + inkscape:transform-center-x="-2.8778231" /> diff --git a/guiscrcpy/version.py b/guiscrcpy/version.py index f23ffdba..169baab9 100644 --- a/guiscrcpy/version.py +++ b/guiscrcpy/version.py @@ -20,4 +20,5 @@ """ -VERSION = '4.0.alpha1' +VERSION = '4.0.a3' +RUNNING = "PYTHON_SRC" \ No newline at end of file diff --git a/releaser b/releaser index 623d6a46..bde1ad96 100755 --- a/releaser +++ b/releaser @@ -140,7 +140,7 @@ except FileNotFoundError: long_description = \\ "Open Source Android Screen Mirroring System by @srevinsaju" -requirements = ['PyQt5>=5.14,<5.15', 'pynput'] +requirements = ['PyQt5>=5.14,<5.16', 'pynput'] if platform.system() == 'Windows': requirements.extend(['pywin32', 'psutil']) elif platform.system() == 'Linux': @@ -165,7 +165,7 @@ setup( license='GPL v3', author='srevinsaju', author_email="srevin03@gmail.com", - packages=['guiscrcpy'], + packages=['guiscrcpy', 'guiscrcpy.lib.mapper', 'guiscrcpy.network', 'guiscrcpy.platform', 'guiscrcpy.theme', 'guiscrcpy.ui', 'guiscrcpy.ux'], data_files=data_files, extras_require={extras}, url="https://srevinsaju.github.io/guiscrcpy", diff --git a/setup.py b/setup.py index 2a099362..97407d97 100755 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ long_description = \ "Open Source Android Screen Mirroring System by @srevinsaju" -requirements = ['PyQt5>=5.14,<5.15', 'pynput'] +requirements = ['PyQt5>=5.14,<5.16', 'pynput'] if platform.system() == 'Windows': requirements.extend(['pywin32', 'psutil']) elif platform.system() == 'Linux': @@ -53,14 +53,14 @@ setup( name='guiscrcpy', - version='4.0.alpha1', + version='4.0.a3', description='An Open Source - Fast - Android Screen Mirroring system.', long_description=long_description, long_description_content_type='text/markdown', license='GPL v3', author='srevinsaju', author_email="srevin03@gmail.com", - packages=['guiscrcpy'], + packages=['guiscrcpy', 'guiscrcpy.lib.mapper', 'guiscrcpy.network', 'guiscrcpy.platform', 'guiscrcpy.theme', 'guiscrcpy.ui', 'guiscrcpy.ux'], data_files=data_files, extras_require={'pyqt5': 'PyQt5', 'pyside2': 'PySide2'}, url="https://srevinsaju.github.io/guiscrcpy",