diff --git a/InputRedirectionClient-Qt.pro b/InputRedirectionClient-Qt-Android-Redux.pro similarity index 61% rename from InputRedirectionClient-Qt.pro rename to InputRedirectionClient-Qt-Android-Redux.pro index 4295a1a..60db5f1 100644 --- a/InputRedirectionClient-Qt.pro +++ b/InputRedirectionClient-Qt-Android-Redux.pro @@ -8,7 +8,7 @@ QT += core gui network gamepad greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -TARGET = InputRedirectionClient-Qt +TARGET = InputRedirectionClient-Qt-Android-Redux TEMPLATE = app # The following define makes your compiler emit warnings if you use @@ -24,12 +24,12 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += main.cpp \ + configwindow.cpp \ global.cpp \ gpmanager.cpp \ - touchscreen.cpp \ - configwindow.cpp \ settings.cpp \ - shortcut.cpp + shortcut.cpp \ + touchscreen.cpp #HEADERS += widget.h @@ -43,3 +43,27 @@ HEADERS += \ settings.h \ tsshortcut.h \ shortcut.h + +DISTFILES += \ + logo/192x192.png \ + logo/192x192_v2.png \ + logo/48x48.png \ + logo/48x48_v2.png \ + logo/512x512.png \ + logo/512x512_v2.png \ + logo/96x96.png \ + logo/96x96_v2.png \ + android/AndroidManifest.xml \ + android/gradle/wrapper/gradle-wrapper.jar \ + android/gradlew \ + android/res/values/libs.xml \ + android/build.gradle \ + android/gradle/wrapper/gradle-wrapper.properties \ + android/gradlew.bat \ + logo/InputRedirectionClient.png \ + logo/InputRedirectionClient-old.png + +RESOURCES += \ + images.qrc + +ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android diff --git a/README.md b/README.md index 0e11ae7..bb49339 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,19 @@ -# InputRedirectionClient-Qt -Input redirection client for the 3DS using QtGamepad +# InputRedirectionClient-Qt for Android +

+ IRC-Qt-Android Logo +

-Supported platforms: +Input redirection client for the 3DS using QtGamepad redesigned for Android. -* Windows (via xinput, if you don't have a Xbox controller you should use x360ce) -* Linux (via evdev) -* OSX -* maybe others? + Supported platforms: + + Optimized for : + * Android (4.1 and above via InputDevice API) + + Non-optimized for (but also work) : + * Windows (via xinput, if you don't have a Xbox controller you should use x360ce) + * Linux (via evdev) + * OSX + * maybe others? If you have multiple controllers connected at the same time, this software will combine their inputs. diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 0000000..cbed4c5 --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..e490a8b --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,57 @@ +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:2.2.3' + } +} + +allprojects { + repositories { + jcenter() + } +} + +apply plugin: 'com.android.application' + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) +} + +android { + /******************************************************* + * The following variables: + * - androidBuildToolsVersion, + * - androidCompileSdkVersion + * - qt5AndroidDir - holds the path to qt android files + * needed to build any Qt application + * on Android. + * + * are defined in gradle.properties file. This file is + * updated by QtCreator and androiddeployqt tools. + * Changing them manually might break the compilation! + *******************************************************/ + + compileSdkVersion androidCompileSdkVersion.toInteger() + + buildToolsVersion androidBuildToolsVersion + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] + aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] + res.srcDirs = [qt5AndroidDir + '/res', 'res'] + resources.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + assets.srcDirs = ['assets'] + jniLibs.srcDirs = ['libs'] + } + } + + lintOptions { + abortOnError false + } +} diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..2b338a9 Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..894abe4 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Feb 20 10:43:22 EST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip diff --git a/android/gradlew b/android/gradlew new file mode 100644 index 0000000..9a0e761 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="-Xmx1024m -Dfile.encoding=UTF-8" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 0000000..6f3ba07 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS=-Xmx1024m -Dfile.encoding=UTF-8 + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/res/drawable-hdpi/icon.png b/android/res/drawable-hdpi/icon.png new file mode 100644 index 0000000..9738ad7 Binary files /dev/null and b/android/res/drawable-hdpi/icon.png differ diff --git a/android/res/drawable-ldpi/icon.png b/android/res/drawable-ldpi/icon.png new file mode 100644 index 0000000..3c4e892 Binary files /dev/null and b/android/res/drawable-ldpi/icon.png differ diff --git a/android/res/drawable-mdpi/icon.png b/android/res/drawable-mdpi/icon.png new file mode 100644 index 0000000..da60945 Binary files /dev/null and b/android/res/drawable-mdpi/icon.png differ diff --git a/android/res/values/libs.xml b/android/res/values/libs.xml new file mode 100644 index 0000000..9e7e2ee --- /dev/null +++ b/android/res/values/libs.xml @@ -0,0 +1,25 @@ + + + + https://download.qt.io/ministro/android/qt5/qt-5.9 + + + + + + + + + + + + + + + + + + + + diff --git a/configwindow.cpp b/configwindow.cpp index c3ba923..6a05949 100644 --- a/configwindow.cpp +++ b/configwindow.cpp @@ -7,22 +7,40 @@ ConfigWindow::ConfigWindow(QWidget *parent, TouchScreen *ts) : QDialog(parent) this->setWindowTitle(tr("InputRedirectionClient-Qt - Button Config")); comboBoxA = populateItems(variantToButton(settings.value("ButtonA", QGamepadManager::ButtonA))); + comboBoxA->setFocusPolicy(Qt::NoFocus); comboBoxB = populateItems(variantToButton(settings.value("ButtonB", QGamepadManager::ButtonB))); + comboBoxB->setFocusPolicy(Qt::NoFocus); comboBoxX = populateItems(variantToButton(settings.value("ButtonX", QGamepadManager::ButtonX))); + comboBoxX->setFocusPolicy(Qt::NoFocus); comboBoxY = populateItems(variantToButton(settings.value("ButtonY", QGamepadManager::ButtonY))); + comboBoxY->setFocusPolicy(Qt::NoFocus); comboBoxUp = populateItems(variantToButton(settings.value("ButtonUp", QGamepadManager::ButtonUp))); + comboBoxUp->setFocusPolicy(Qt::NoFocus); comboBoxDown = populateItems(variantToButton(settings.value("ButtonDown", QGamepadManager::ButtonDown))); + comboBoxDown->setFocusPolicy(Qt::NoFocus); comboBoxLeft = populateItems(variantToButton(settings.value("ButtonLeft", QGamepadManager::ButtonLeft))); + comboBoxLeft->setFocusPolicy(Qt::NoFocus); comboBoxRight = populateItems(variantToButton(settings.value("ButtonRight", QGamepadManager::ButtonRight))); + comboBoxRight->setFocusPolicy(Qt::NoFocus); comboBoxL = populateItems(variantToButton(settings.value("ButtonL", QGamepadManager::ButtonL1))); + comboBoxL->setFocusPolicy(Qt::NoFocus); comboBoxR = populateItems(variantToButton(settings.value("ButtonR", QGamepadManager::ButtonR1))); + comboBoxR->setFocusPolicy(Qt::NoFocus); comboBoxSelect = populateItems(variantToButton(settings.value("ButtonSelect", QGamepadManager::ButtonSelect))); + comboBoxSelect->setFocusPolicy(Qt::NoFocus); comboBoxStart = populateItems(variantToButton(settings.value("ButtonStart", QGamepadManager::ButtonStart))); + comboBoxStart->setFocusPolicy(Qt::NoFocus); comboBoxZL = populateItems(variantToButton(settings.value("ButtonZL", QGamepadManager::ButtonL2))); + comboBoxZL->setFocusPolicy(Qt::NoFocus); comboBoxZR = populateItems(variantToButton(settings.value("ButtonZR", QGamepadManager::ButtonR2))); + comboBoxZR->setFocusPolicy(Qt::NoFocus); comboBoxHome = populateItems(variantToButton(settings.value("ButtonHome", QGamepadManager::ButtonInvalid))); + comboBoxHome->setFocusPolicy(Qt::NoFocus); comboBoxPower = populateItems(variantToButton(settings.value("ButtonPower", QGamepadManager::ButtonInvalid))); + comboBoxPower->setFocusPolicy(Qt::NoFocus); comboBoxPowerLong = populateItems(variantToButton(settings.value("ButtonPowerLong", QGamepadManager::ButtonInvalid))); + comboBoxPowerLong->setFocusPolicy(Qt::NoFocus); + txtCppVal = new QLineEdit(); txtStickVal = new QLineEdit(); validator = new QIntValidator(); @@ -34,17 +52,27 @@ ConfigWindow::ConfigWindow(QWidget *parent, TouchScreen *ts) : QDialog(parent) txtStickVal->setText(tr("%1").arg(CPAD_BOUND)); txtCppVal->setClearButtonEnabled(true); + txtCppVal->setInputMethodHints(Qt::ImhPreferNumbers); txtStickVal->setClearButtonEnabled(true); + txtStickVal->setInputMethodHints(Qt::ImhPreferNumbers); invertYCheckbox = new QCheckBox(this); + invertYCheckbox->setFocusPolicy(Qt::NoFocus); invertYCppCheckbox = new QCheckBox(this); + invertYCppCheckbox->setFocusPolicy(Qt::NoFocus); swapSticksCheckbox = new QCheckBox(this); + swapSticksCheckbox->setFocusPolicy(Qt::NoFocus); mhCameraCheckbox = new QCheckBox(this); + mhCameraCheckbox->setFocusPolicy(Qt::NoFocus); rsSmashCheckbox = new QCheckBox(this); + rsSmashCheckbox->setFocusPolicy(Qt::NoFocus); rsFaceButtonsCheckbox = new QCheckBox(); + rsFaceButtonsCheckbox->setFocusPolicy(Qt::NoFocus); disableCStickCheckbox = new QCheckBox(); + disableCStickCheckbox->setFocusPolicy(Qt::NoFocus); - saveButton = new QPushButton(tr("&SAVE"), this); + saveButton = new QPushButton(tr("&SAVE 💾"), this); + saveButton->setFocusPolicy(Qt::NoFocus); layout = new QGridLayout(this); @@ -186,7 +214,7 @@ ConfigWindow::ConfigWindow(QWidget *parent, TouchScreen *ts) : QDialog(parent) switch(state) { case Qt::Unchecked: - btnSettings.setMonsterHunterCamera(false); + btnSettings.setMonsterHunterCamera(false); settings.setValue("monsterHunterCamera", false); break; case Qt::Checked: @@ -297,6 +325,12 @@ ConfigWindow::ConfigWindow(QWidget *parent, TouchScreen *ts) : QDialog(parent) }); + connect(saveButton, &QPushButton::released, this, + [this](void) + { + this->hide(); + }); + invertYCheckbox->setChecked(settings.value("invertY", false).toBool()); invertYCppCheckbox->setChecked(settings.value("invertCPPY", false).toBool()); swapSticksCheckbox->setChecked(settings.value("swapSticks", false).toBool()); diff --git a/global.h b/global.h index 887d8d7..d1ce7d4 100644 --- a/global.h +++ b/global.h @@ -104,11 +104,11 @@ class Worker : public QObject { void setPreviousLAxis(double x, double y); void closeThread() { emit finished(); } - explicit Worker(QObject *parent = 0) : QObject(parent) + /*explicit Worker(QObject *parent = 0) : QObject(parent) { previousLeftAxis.x = leftAxis.x; previousLeftAxis.y = leftAxis.y; - } + }*/ ~Worker() { diff --git a/images.qrc b/images.qrc new file mode 100644 index 0000000..f7d9dcc --- /dev/null +++ b/images.qrc @@ -0,0 +1,6 @@ + + + logo/512x512_v2.png + logo/InputRedirectionClient.png + + diff --git a/logo/192x192.png b/logo/192x192.png new file mode 100644 index 0000000..02a79b5 Binary files /dev/null and b/logo/192x192.png differ diff --git a/logo/192x192_v2.png b/logo/192x192_v2.png new file mode 100644 index 0000000..9738ad7 Binary files /dev/null and b/logo/192x192_v2.png differ diff --git a/logo/48x48.png b/logo/48x48.png new file mode 100644 index 0000000..644add4 Binary files /dev/null and b/logo/48x48.png differ diff --git a/logo/48x48_v2.png b/logo/48x48_v2.png new file mode 100644 index 0000000..3c4e892 Binary files /dev/null and b/logo/48x48_v2.png differ diff --git a/logo/512x512.png b/logo/512x512.png new file mode 100644 index 0000000..164f813 Binary files /dev/null and b/logo/512x512.png differ diff --git a/logo/512x512_v2.png b/logo/512x512_v2.png new file mode 100644 index 0000000..87fd210 Binary files /dev/null and b/logo/512x512_v2.png differ diff --git a/logo/96x96.png b/logo/96x96.png new file mode 100644 index 0000000..9eb9ae9 Binary files /dev/null and b/logo/96x96.png differ diff --git a/logo/96x96_v2.png b/logo/96x96_v2.png new file mode 100644 index 0000000..da60945 Binary files /dev/null and b/logo/96x96_v2.png differ diff --git a/logo/InputRedirectionClient-old.png b/logo/InputRedirectionClient-old.png new file mode 100644 index 0000000..98aa317 Binary files /dev/null and b/logo/InputRedirectionClient-old.png differ diff --git a/logo/InputRedirectionClient.png b/logo/InputRedirectionClient.png new file mode 100644 index 0000000..de28831 Binary files /dev/null and b/logo/InputRedirectionClient.png differ diff --git a/logo/logo.svg b/logo/logo.svg new file mode 100644 index 0000000..6a0ccdd --- /dev/null +++ b/logo/logo.svg @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main.cpp b/main.cpp index 0fa4a7f..a34ec85 100644 --- a/main.cpp +++ b/main.cpp @@ -4,6 +4,7 @@ #include "mainwidget.h" #include "gpmanager.h" +#include "global.h" #include #include @@ -17,16 +18,18 @@ int main(int argc, char *argv[]) QThread* thread = new QThread(); QTimer timer; timer.setInterval(20); - timer.moveToThread(thread); - worker.moveToThread(thread); + + Worker* worker = new Worker(); + worker->moveToThread(thread); QObject::connect(thread, SIGNAL (started()), &timer, SLOT (start())); - QObject::connect(&worker, SIGNAL (finished()), thread, SLOT (quit())); + QObject::connect(worker, SIGNAL (finished()), thread, SLOT (quit())); QObject::connect(thread, SIGNAL (finished()), thread, SLOT (deleteLater())); - QObject::connect(&timer, SIGNAL(timeout()), &worker, SLOT(sendFrame())); + QObject::connect(worker, SIGNAL (finished()), worker, SLOT (deleteLater())); + QObject::connect(&timer, SIGNAL (timeout()), worker, SLOT(sendFrame())); thread->start(); a.exec(); - worker.closeThread(); + worker->closeThread(); return 0; } diff --git a/mainwidget.h b/mainwidget.h index 2a3dafe..c7d4090 100644 --- a/mainwidget.h +++ b/mainwidget.h @@ -5,6 +5,7 @@ #include #include +#include #include "touchscreen.h" #include "configwindow.h" @@ -23,10 +24,15 @@ private slots: *clearImageButton, *configGamepadButton; QLineEdit *addrLineEdit; QSlider *touchOpacitySlider; + QLabel *creatorLabel, *titleLabel, *instructionsLabel; ConfigWindow *settingsConfig; + QPixmap *logo, *title; + QScreen *screen; + QFrame *lineA, *lineB, *lineC; public: TouchScreen *touchScreen; + QString version = QCoreApplication::applicationVersion(); Widget(QWidget *parent = nullptr) : QWidget(parent) { @@ -34,22 +40,73 @@ private slots: addrLineEdit = new QLineEdit(this); addrLineEdit->setClearButtonEnabled(true); + addrLineEdit->setInputMethodHints(Qt::ImhPreferNumbers); formLayout = new QFormLayout(); - formLayout->addRow(tr("IP &address"), addrLineEdit); + formLayout->addRow(tr("IP address 📡"), addrLineEdit); touchOpacitySlider = new QSlider(Qt::Horizontal); touchOpacitySlider->setRange(0, 10); touchOpacitySlider->setValue(10); touchOpacitySlider->setTickInterval(1); - formLayout->addRow(tr("TS &Opacity"), touchOpacitySlider); - - homeButton = new QPushButton(tr("&Home"), this); - powerButton = new QPushButton(tr("&Power"), this); - longPowerButton = new QPushButton(tr("Power (&long)"), this); - settingsConfigButton = new QPushButton(tr("&Settings"), this); - clearImageButton = new QPushButton(tr("&Clear Image"), this); - configGamepadButton = new QPushButton(tr("&Configure Custom Gamepad")); + //formLayout->addRow(tr("TS Opacity"), touchOpacitySlider); + + homeButton = new QPushButton(tr("Home 🏠"), this); + homeButton->setFocusPolicy(Qt::NoFocus); + powerButton = new QPushButton(tr("Power ⚫"), this); + powerButton->setFocusPolicy(Qt::NoFocus); + longPowerButton = new QPushButton(tr("Power (long) ⚫⚫⚫"), this); + longPowerButton->setFocusPolicy(Qt::NoFocus); + settingsConfigButton = new QPushButton(tr("Settings ⚙️"), this); + settingsConfigButton->setFocusPolicy(Qt::NoFocus); + //clearImageButton = new QPushButton(tr("Clear Image"), this); + configGamepadButton = new QPushButton(tr("Configure Custom Gamepad 🎮")); + configGamepadButton->setFocusPolicy(Qt::NoFocus); + + QScreen *screen = QApplication::screens().at(0); + titleLabel = new QLabel; + titleLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Maximum); + QPixmap title(":/myressources/logo/InputRedirectionClient.png"); + titleLabel->setPixmap(title.scaledToWidth(screen->availableGeometry().width()-20)); + titleLabel->setAlignment(Qt::AlignCenter); + + lineA = new QFrame; + lineA->setFrameShape(QFrame::HLine); + lineA->setFrameShadow(QFrame::Sunken); + + lineB = new QFrame; + lineB->setFrameShape(QFrame::HLine); + lineB->setFrameShadow(QFrame::Sunken); + + lineC = new QFrame; + lineC->setFrameShape(QFrame::HLine); + lineC->setFrameShadow(QFrame::Sunken); + + instructionsLabel = new QLabel; + instructionsLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + instructionsLabel->setAlignment(Qt::AlignLeft); + instructionsLabel->setText("Instructions:" + "
1. Start InputRedirection on your 3DS via Rosalina menu (Press L+⬇️+Select)." + "
2. Connect your Gamepad to your Android device.
" + "
3. Enter the IP address displayed on your 3DS in the IRC application.
" + "
ℹ️ Work via Wi-Fi or via Mobile Data if both devices share the same network.
"); + instructionsLabel->setTextFormat(Qt::RichText); + instructionsLabel->setWordWrap(true); + + creatorLabel = new QLabel; + creatorLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + creatorLabel->setAlignment(Qt::AlignCenter); + creatorLabel->setText("Created by TuxSH" + "
Based on mastermune & gbrown5's forks" + "
Version "+version+" for Android by JambonBeurreMan"); + creatorLabel->setTextFormat(Qt::RichText); + creatorLabel->setOpenExternalLinks(true); + + if(screen->availableGeometry().height()<=800) + { + instructionsLabel->setStyleSheet("font: 10pt;"); + creatorLabel->setStyleSheet("font: 10pt"); + } setContextMenuPolicy(Qt::CustomContextMenu); @@ -61,13 +118,26 @@ private slots: configGamepadButton->setVisible(false); } + layout->setContentsMargins(10,10,10,0); + layout->addWidget(titleLabel); + layout->addSpacing(10); layout->addLayout(formLayout); + layout->addWidget(lineA); layout->addWidget(homeButton); + if(screen->availableGeometry().height()>=1280) + { + layout->addSpacing(50); + } layout->addWidget(powerButton); layout->addWidget(longPowerButton); layout->addWidget(configGamepadButton); layout->addWidget(settingsConfigButton); - layout->addWidget(clearImageButton); + //layout->addWidget(clearImageButton); + layout->addWidget(lineB); + layout->addWidget(instructionsLabel); + layout->addStretch(1); + layout->addWidget(lineC); + layout->addWidget(creatorLabel); gpConfigurator = new GamepadConfigurator(); @@ -165,20 +235,20 @@ private slots: } else settingsConfig->hide(); }); - connect(clearImageButton, &QPushButton::released, this, + /*connect(clearImageButton, &QPushButton::released, this, [this](void) { touchScreen->clearImage(); - }); + });*/ - connect(touchOpacitySlider, &QSlider::valueChanged, this, + /*connect(touchOpacitySlider, &QSlider::valueChanged, this, [this](int value) { touchScreen->setWindowOpacity(value / 10.0); touchScreen->update(); - }); + });*/ - touchScreen = new TouchScreen(nullptr); + //touchScreen = new TouchScreen(nullptr); settingsConfig = new ConfigWindow(nullptr, touchScreen); this->setWindowTitle(tr("InputRedirectionClient-Qt")); @@ -188,8 +258,8 @@ private slots: void show(void) { QWidget::show(); - touchScreen->move(this->x() + this->width() + 5,this->y()); - touchScreen->show(); + //touchScreen->move(this->x() + this->width() + 5,this->y()); + //touchScreen->show(); settingsConfig->hide(); } @@ -209,22 +279,22 @@ private slots: { settings.remove(tr("tsShortcut%1").arg(i)); } - touchScreen->close(); + //touchScreen->close(); settingsConfig->close(); - touchScreen->setTouchScreenPressed(false); - delete touchScreen; + //touchScreen->setTouchScreenPressed(false); + //delete touchScreen; ev->accept(); } //Move touchscreen window with main window if moved void moveEvent(QMoveEvent *event) { - touchScreen->move(touchScreen->pos() + (event->pos() - event->oldPos())); + //touchScreen->move(touchScreen->pos() + (event->pos() - event->oldPos())); } //When main window is opened, load shortcut settings - void showEvent(QShowEvent* event) + void showEvent(QShowEvent *event) { qRegisterMetaType("ShortCut"); qRegisterMetaTypeStreamOperators("ShortCut");