Compare commits

..

No commits in common. "master" and "061" have entirely different histories.
master ... 061

39 changed files with 5241 additions and 5427 deletions

33
.classpath Normal file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/test/main"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.fx.ide.jdt.core.JAVAFX_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

3
.gitignore vendored
View File

@ -50,6 +50,3 @@ client_secret.json
.directory .directory
target/ target/
cemu_UI.jar cemu_UI.jar
.classpath
.project
.settings/*

29
.project Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>cemu_UI</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,13 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

1
.travis.yml Normal file
View File

@ -0,0 +1 @@
language: java

View File

@ -1,13 +1,7 @@
# Contributing to cemu_UI # Contributing to cemu_UI
The following is a set of guidelines for contributing to cemu_UI. The following is a set of guidelines for contributing to cemu_UI.
## Translating ## Java Sytleguide
If you don't want to contibute any code you can support this project by translating it! The translation files are stored in "src/main/resources/locals".
# Contributing code
If you want to contibute code please read the java code styleguide.
## Java code sytleguide
If your willing to contribute to cemu_UI please us the following example as guide and rules to design your code. If your willing to contribute to cemu_UI please us the following example as guide and rules to design your code.
* Use names for methods and variables that clarify their purpose. (This will help a lot to understand the code) * Use names for methods and variables that clarify their purpose. (This will help a lot to understand the code)
* Use as many spaces as necessary to make the code clear, but as little as possible. * Use as many spaces as necessary to make the code clear, but as little as possible.

View File

@ -1,17 +1,16 @@
# cemu_UI # cemu_UI
![Total Downloads](https://img.shields.io/github/downloads/Seil0/cemu_UI/total.svg?style=flat-square) ![Total Downloads](https://img.shields.io/github/downloads/Seil0/cemu_UI/total.svg?style=flat-square)
[![Latest](https://img.shields.io/badge/release-085-blue.svg?style=flat-square)](https://git.mosad.xyz/Seil0/cemu_UI/releases) [![](https://img.shields.io/travis/Seil0/cemu_UI/master.svg?style=flat-square)](https://travis-ci.org/Seil0/cemu_UI)
[![Latest](https://img.shields.io/github/release/Seil0/cemu_UI/all.svg?style=flat-square)](https://github.com/Seil0/cemu_UI/releases)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg?style=flat-square)](https://www.gnu.org/licenses/gpl-3.0) [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg?style=flat-square)](https://www.gnu.org/licenses/gpl-3.0)
cemu_UI is a simple, material design graphical frontend for [cemu](http://cemu.info/), a Wii U emulator. Downloads can be found [here](https://git.mosad.xyz/Seil0/cemu_UI/releases). cemu_UI is a simple, material design graphical frontend for [cemu](http://cemu.info/), a Wii U emulator. Downloads can be found [here](https://github.com/Seil0/cemu_UI/releases).
## Installation ## Installation
Simply download the cemu_UI.jar from [Releases](https://git.mosad.xyz/Seil0/cemu_UI/releases), make sure you have the latest version of java 8 oracle jre/jdk installed and open the file. cemu_UI creats a new directory "C:\Users\USERNAME\Documents\cemu_UI", where the database, settings and covers are stored. **first start can take while!** Simply download the cemu_UI.jar from [releases](https://github.com/Seil0/cemu_UI/releases), make sure you have the latest version of java 8 oracle jre/jdk installed and open the file. cemu_UI creats a new directory "C:\Users\USERNAME\Documents\cemu_UI", where the database, settings and covers are stored. **first start can take while!**
If you want to use the cloud sync function read the [wiki](https://git.mosad.xyz/Seil0/cemu_UI/wiki#cloud-savegame-syncronisation) carefully! If you want to use the cloud sync function read the [wiki](https://github.com/Seil0/cemu_UI/wiki#cloud-savegame-syncronisation) carefully!
### [FAQ](https://git.mosad.xyz/Seil0/cemu_UI/wiki#faq)
## Features ## Features
@ -21,17 +20,23 @@ If you want to use the cloud sync function read the [wiki](https://git.mosad.xyz
* add updates and dlcs easier (only adding not downloading!) * add updates and dlcs easier (only adding not downloading!)
* automatic rom detection (only .rpx files with a app.xml) * automatic rom detection (only .rpx files with a app.xml)
* customisable UI * customisable UI
* [sync savegames via google drive](https://git.mosad.xyz/Seil0/cemu_UI/wiki) * [sync savegames via google drive](https://github.com/Seil0/cemu_UI/wiki)
* [smmdb api](https://github.com/Tarnadas/smmdb) integration * [smmdb api](https://github.com/Tarnadas/smmdb) integration
## [planed Features](https://git.mosad.xyz/Seil0/cemu_UI/milestones) ## [planed Features](https://github.com/Seil0/cemu_UI/projects/1) (no ETA)
* Controller support * Controller support
* more UI improvements
* support more rom file formats in automatic detection
### If you have another idea, make a new issue! ### If you have another idea, make a "new issue" with the ![#f03c15](https://placehold.it/15/fbca04/000000?text=+)`idea` lable
### [building from source](https://git.mosad.xyz/Seil0/cemu_UI/wiki/Documentation) ## [FAQ](https://github.com/Seil0/cemu_UI/wiki#faq)
### [building from source](https://github.com/Seil0/cemu_UI/wiki/Documantation)
## Screenshots ## Screenshots
![Screenshot](https://www.mosad.xyz/images/cemu_UI_MainWindow.webp) ![Screenshot](/downloadContent/cemu_UI4.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

File diff suppressed because it is too large Load Diff

138
pom.xml
View File

@ -1,18 +1,19 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com</groupId> <groupId>com</groupId>
<artifactId>cemu_UI</artifactId> <artifactId>cemu_UI</artifactId>
<version>0.3.2-SNAPSHOT</version> <version>0.2.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>cemu_UI</name> <name>cemu_UI</name>
<description>cemu_UI is a simple, material design graphical frontend for cemu, a Wii U emulator</description> <url>http://www.kellerkinder.xyz</url>
<url>https://www.mosad.xyz</url>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties> </properties>
<dependencies> <dependencies>
@ -20,62 +21,44 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version> <version>3.8.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>12.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>12.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>12.0.1</version>
</dependency>
<dependency> <dependency>
<groupId>com.jfoenix</groupId> <groupId>com.jfoenix</groupId>
<artifactId>jfoenix</artifactId> <artifactId>jfoenix</artifactId>
<version>9.0.9</version> <version>1.11.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.eclipsesource.minimal-json</groupId> <groupId>com.eclipsesource.minimal-json</groupId>
<artifactId>minimal-json</artifactId> <artifactId>minimal-json</artifactId>
<version>0.9.5</version> <version>0.9.4</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.xerial</groupId> <groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId> <artifactId>sqlite-jdbc</artifactId>
<version>3.27.2.1</version> <version>3.21.0.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId> <artifactId>log4j-api</artifactId>
<version>2.11.2</version> <version>2.9.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId> <artifactId>log4j-core</artifactId>
<version>2.11.2</version> <version>2.9.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.6</version> <version>2.5</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-vfs2 --> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-vfs2 -->
@ -92,6 +75,14 @@
<version>1.11</version> <version>1.11</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/io.datafx/flow -->
<dependency>
<groupId>io.datafx</groupId>
<artifactId>flow</artifactId>
<version>8.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.lingala.zip4j/zip4j --> <!-- https://mvnrepository.com/artifact/net.lingala.zip4j/zip4j -->
<dependency> <dependency>
<groupId>net.lingala.zip4j</groupId> <groupId>net.lingala.zip4j</groupId>
@ -99,7 +90,7 @@
<version>1.3.2</version> <version>1.3.2</version>
</dependency> </dependency>
<!-- Google Drive-API libraries --> <!-- Google Drive-API libraries-->
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging --> <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency> <dependency>
<groupId>commons-logging</groupId> <groupId>commons-logging</groupId>
@ -107,39 +98,69 @@
<version>1.1.1</version> <version>1.1.1</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.google.api-client/google-api-client -->
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.23.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.apis/google-api-services-drive --> <!-- https://mvnrepository.com/artifact/com.google.apis/google-api-services-drive -->
<dependency> <dependency>
<groupId>com.google.apis</groupId> <groupId>com.google.apis</groupId>
<artifactId>google-api-services-drive</artifactId> <artifactId>google-api-services-drive</artifactId>
<version>v3-rev136-1.25.0</version> <version>v3-rev87-1.23.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.google.http-client/google-http-client --> <!-- https://mvnrepository.com/artifact/com.google.http-client/google-http-client -->
<dependency> <dependency>
<groupId>com.google.http-client</groupId> <groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId> <artifactId>google-http-client</artifactId>
<version>1.25.0</version> <version>1.23.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.google.http-client/google-http-client-jackson2 --> <!-- https://mvnrepository.com/artifact/com.google.http-client/google-http-client-jackson2 -->
<dependency> <dependency>
<groupId>com.google.http-client</groupId> <groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId> <artifactId>google-http-client-jackson2</artifactId>
<version>1.25.0</version> <version>1.23.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.oauth-client/google-oauth-client -->
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client</artifactId>
<version>1.23.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.oauth-client/google-oauth-client-java6 -->
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-java6</artifactId>
<version>1.23.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.google.oauth-client/google-oauth-client-jetty --> <!-- https://mvnrepository.com/artifact/com.google.oauth-client/google-oauth-client-jetty -->
<dependency> <dependency>
<groupId>com.google.oauth-client</groupId> <groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId> <artifactId>google-oauth-client-jetty</artifactId>
<version>1.25.0</version> <version>1.23.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId> <artifactId>jackson-core</artifactId>
<version>2.9.7</version> <version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0-b01</version>
<scope>provided</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.mortbay.jetty/jetty --> <!-- https://mvnrepository.com/artifact/org.mortbay.jetty/jetty -->
@ -149,43 +170,23 @@
<version>6.1.26</version> <version>6.1.26</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.mortbay.jetty/jetty-util -->
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>6.1.26</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.cemu_UI.application.Main</mainClass>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@ -193,18 +194,17 @@
<goal>shade</goal> <goal>shade</goal>
</goals> </goals>
<configuration> <configuration>
<finalName>cemu_UI</finalName>
<shadedArtifactAttached>true</shadedArtifactAttached> <shadedArtifactAttached>true</shadedArtifactAttached>
<transformers> <transformers>
<transformer <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.cemu_UI.application.Main</mainClass>
<mainClass>com.cemu_UI.application.JavaFX11Main</mainClass>
</transformer> </transformer>
</transformers> </transformers>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>

View File

@ -1,8 +0,0 @@
package com.cemu_UI.application;
public class JavaFX11Main {
public static void main(String[] args) {
Main.main(args);
}
}

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -27,6 +27,7 @@ import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.util.Optional;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -34,45 +35,52 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import com.cemu_UI.controller.CloudController; import com.cemu_UI.controller.CloudController;
import com.cemu_UI.controller.XMLController;
import com.cemu_UI.uiElements.JFXInfoAlert;
import com.cemu_UI.uiElements.JFXOkayCancelAlert;
import javafx.application.Application; import javafx.application.Application;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.AnchorPane;
public class Main extends Application { public class Main extends Application {
private final String gamesDBdownloadURL = "https://git.mosad.xyz/Seil0/cemu_UI/raw/branch/master/downloadContent/games.db"; Stage primaryStage;
private static Main main; public MainWindowController mainWindowController; // TODO find a better way
private static XMLController xmlController; CloudController cloudController;
private MainWindowController mainWindowController; AnchorPane pane;
private CloudController cloudController; Scene scene; // TODO make private
private Stage primaryStage; private static String userHome = System.getProperty("user.home");
private AnchorPane pane; private static String userName = System.getProperty("user.name");
private Scene scene; private static String osName = System.getProperty("os.name");
private static String osArch = System.getProperty("os.arch");
private static String osVers = System.getProperty("os.version");
private static String javaVers = System.getProperty("java.version");
private static String javaVend= System.getProperty("java.vendor");
private String gamesDBdownloadURL = "https://github.com/Seil0/cemu_UI/raw/master/downloadContent/games.db";
public String dirWin = userHome + "/Documents/cemu_UI"; // Windows: C:/Users/"User"/Documents/cemu_UI
public String dirLinux = userHome + "/cemu_UI"; // Linux: /home/"User"/cemu_UI
private File directory;
private File configFile;
private File gamesDBFile;
@SuppressWarnings("unused")
private File localDB;
private File pictureCache;
private static Logger LOGGER; private static Logger LOGGER;
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
try { try {
LOGGER.info("OS: " + XMLController.getOsName() + " " + XMLController.getOsVers() + " " + XMLController.getOsVers()); LOGGER.info("OS: " + osName + " " + osVers + " " + osArch);
LOGGER.info("Java: " + XMLController.getJavaVend() + " " + XMLController.getJavaVers()); LOGGER.info("Java: " + javaVend + " " + javaVers);
LOGGER.info("User: " + XMLController.getUserName() + " " + XMLController.getUserHome()); LOGGER.info("User: " + userName + " " + userHome);
this.primaryStage = primaryStage; this.primaryStage = primaryStage;
mainWindowController = new MainWindowController();
main = this;
mainWindow(); mainWindow();
initActions(); initActions();
} catch (Exception e) { } catch (Exception e) {
@ -84,61 +92,69 @@ public class Main extends Application {
private void mainWindow(){ private void mainWindow(){
try { try {
FXMLLoader loader = new FXMLLoader(); FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/fxml/MainWindow.fxml")); loader.setLocation(ClassLoader.getSystemResource("fxml/MainWindow.fxml"));
loader.setController(mainWindowController);
pane = (AnchorPane) loader.load(); pane = (AnchorPane) loader.load();
primaryStage.setMinWidth(1130);
primaryStage.setMinHeight(600 + 34);
primaryStage.setTitle("cemu_UI"); primaryStage.setTitle("cemu_UI");
// primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream(""))); //adds application icon // primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/resources/Homeflix_Icon_64x64.png"))); //adds application icon
primaryStage.setOnCloseRequest(event -> System.exit(0));
// generate window mainWindowController = loader.getController(); // Link of FXMLController and controller class
scene = new Scene(pane); // create new scene, append pane to scene mainWindowController.setMain(this); // call setMain
scene.getStylesheets().add(Main.class.getResource("/css/MainWindows.css").toExternalForm()); cloudController = new CloudController(mainWindowController); // call cloudController constructor
primaryStage.setScene(scene); // append scene to stage
primaryStage.show(); // show stage
cloudController = CloudController.getInstance(mainWindowController); // call cloudController constructor // get OS and the specific paths
if (osName.equals("Linux")) {
directory = new File(dirLinux);
configFile = new File(dirLinux + "/config.xml");
gamesDBFile = new File(dirLinux + "/games.db");
localDB = new File(dirLinux+"/localRoms.db");
pictureCache= new File(dirLinux+"/picture_cache");
} else {
directory = new File(dirWin);
configFile = new File(dirWin + "/config.xml");
gamesDBFile = new File(dirWin + "/games.db");
localDB = new File(dirWin+"/localRoms.db");
pictureCache= new File(dirWin+"/picture_cache");
}
// startup checks // startup checks
// check if client_secret.json is present // check if client_secret.jason is present
if (Main.class.getResourceAsStream("/client_secret.json") == null) { if (Main.class.getResourceAsStream("/client_secret.json") == null) {
LOGGER.error("client_secret is missing!!!!!"); LOGGER.error("client_secret is missing!!!!!");
JFXInfoAlert noCSAlert = new JFXInfoAlert("Error", Alert alert = new Alert(AlertType.ERROR);
"client_secret is missing! Please contact the maintainer. \n" alert.setTitle("cemu_UI");
+ "If you compiled cemu_UI by yourself see: \n" alert.setHeaderText("Error");
+ "https://git.mosad.xyz/Seil0/cemu_UI/wiki/Documantation", alert.setContentText("client_secret is missing! Please contact the maintainer. \nIf you compiled cemu_UI by yourself see: \nhttps://github.com/Seil0/cemu_UI/wiki/Documantation");
"-fx-button-type: RAISED; -fx-background-color: #00a8cc; -fx-text-fill: BLACK;", primaryStage); alert.showAndWait();
noCSAlert.showAndWait();
} }
if (!XMLController.getDirCemuUI().exists()) { if (!directory.exists()) {
LOGGER.info("creating cemu_UI directory"); LOGGER.info("creating cemu_UI directory");
XMLController.getDirCemuUI().mkdir(); directory.mkdir();
XMLController.getPictureCache().mkdir(); pictureCache.mkdir();
} }
if (!XMLController.getConfigFile().exists()) { if (!configFile.exists()) {
LOGGER.info("firststart, setting default values"); LOGGER.info("firststart, setting default values");
firstStart(); firstStart();
xmlController.saveSettings(); mainWindowController.setColor("00a8cc");
mainWindowController.setAutoUpdate(false);
mainWindowController.setxPosHelper(0);
mainWindowController.saveSettings();
Runtime.getRuntime().exec("java -jar cemu_UI.jar"); //start again (preventing Bugs)
System.exit(0); //finishes itself
} }
if (!XMLController.getPictureCache().exists()) { if (pictureCache.exists() != true) {
XMLController.getPictureCache().mkdir(); pictureCache.mkdir();
} }
if (!XMLController.getRference_gamesFile().exists()) { if (gamesDBFile.exists() != true) {
if (XMLController.getGamesDBFile().exists()) {
XMLController.getGamesDBFile().delete();
}
try { try {
LOGGER.info("downloading ReferenceGameList.db... "); LOGGER.info("downloading games.db... ");
URL website = new URL(gamesDBdownloadURL); URL website = new URL(gamesDBdownloadURL);
ReadableByteChannel rbc = Channels.newChannel(website.openStream()); ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(XMLController.getRference_gamesFile()); FileOutputStream fos = new FileOutputStream(gamesDBFile);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close(); fos.close();
LOGGER.info("finished downloading games.db"); LOGGER.info("finished downloading games.db");
@ -147,68 +163,55 @@ public class Main extends Application {
} }
} }
// init here as it loads the games to the mwc and the gui, therefore the window must exist // loading settings and initialize UI, dbController.main() loads all databases
mainWindowController.init(); mainWindowController.init();
mainWindowController.dbController.main();
// if cloud sync is activated start sync // if cloud sync is activated start sync
if (XMLController.isCloudSync()) { if(mainWindowController.isCloudSync()) {
cloudController.initializeConnection(XMLController.getCloudService(), XMLController.getCemuPath()); cloudController.initializeConnection(mainWindowController.getCloudService(), mainWindowController.getCemuPath());
cloudController.sync(XMLController.getCloudService(), XMLController.getCemuPath(), XMLController.getDirCemuUIPath()); cloudController.stratupCheck(mainWindowController.getCloudService(), mainWindowController.getCemuPath());
} }
mainWindowController.addUIData();
scene = new Scene(pane); // create new scene, append pane to scene
scene.getStylesheets().add(Main.class.getResource("/css/MainWindows.css").toExternalForm());
primaryStage.setScene(scene); // append scene to stage
primaryStage.show(); // show stage
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
public static void main(String[] args) { private void firstStart(){
String logPath = ""; Alert alert = new Alert(AlertType.CONFIRMATION); // new alert with file-chooser
alert.setTitle("cemu_UI");
alert.setHeaderText("cemu installation");
alert.setContentText("please select your cemu installation");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK) {
DirectoryChooser directoryChooser = new DirectoryChooser();
File selectedDirectory = directoryChooser.showDialog(primaryStage);
mainWindowController.setCemuPath(selectedDirectory.getAbsolutePath());
if (System.getProperty("os.name").contains("Windows")) {
logPath = System.getProperty("user.home") + "/Documents/cemu_UI/app.log";
} else { } else {
logPath = System.getProperty("user.home") + "/cemu_UI/app.log"; mainWindowController.setCemuPath(null);
} }
System.setProperty("logFilename", logPath); Alert alert2 = new Alert(AlertType.CONFIRMATION); // new alert with file-chooser
File logFile = new File(logPath); alert2.setTitle("cemu_UI");
logFile.delete(); alert2.setHeaderText("rom directory");
LOGGER = LogManager.getLogger(Main.class.getName()); alert2.setContentText("please select your rom directory");
xmlController = new XMLController(); Optional<ButtonType> result2 = alert2.showAndWait();
launch(args); if (result2.get() == ButtonType.OK) {
DirectoryChooser directoryChooser = new DirectoryChooser();
File selectedDirectory = directoryChooser.showDialog(primaryStage);
mainWindowController.setRomPath(selectedDirectory.getAbsolutePath());
} else {
mainWindowController.setRomPath(null);
} }
private void firstStart() {
JFXOkayCancelAlert cemuInstallAlert = new JFXOkayCancelAlert("cemu installation",
"please select your cemu installation",
"-fx-button-type: RAISED; -fx-background-color: #00a8cc; -fx-text-fill: BLACK;", primaryStage);
cemuInstallAlert.setOkayAction(e -> {
DirectoryChooser directoryChooser = new DirectoryChooser();
File selectedDirectory = directoryChooser.showDialog(primaryStage);
XMLController.setCemuPath(selectedDirectory.getAbsolutePath());
});
cemuInstallAlert.setCancelAction(e -> {
XMLController.setCemuPath(null);
LOGGER.info("Action canceld by user!");
});
cemuInstallAlert.showAndWait();
JFXOkayCancelAlert romDirectoryAlert = new JFXOkayCancelAlert("rom directory",
"please select your rom directory",
"-fx-button-type: RAISED; -fx-background-color: #00a8cc; -fx-text-fill: BLACK;", primaryStage);
romDirectoryAlert.setOkayAction(e -> {
DirectoryChooser directoryChooser = new DirectoryChooser();
File selectedDirectory = directoryChooser.showDialog(primaryStage);
XMLController.setRomDirectoryPath(selectedDirectory.getAbsolutePath());
});
romDirectoryAlert.setCancelAction(e -> {
XMLController.setRomDirectoryPath(null);
LOGGER.info("Action canceld by user!");
});
romDirectoryAlert.showAndWait();
} }
private void initActions() { private void initActions() {
@ -220,6 +223,14 @@ public class Main extends Application {
@Override @Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, final Number newValue) { public void changed(ObservableValue<? extends Number> observable, Number oldValue, final Number newValue) {
int xPosHelperMax = (int) Math.floor((mainWindowController.getMainAnchorPane().getWidth() - 36) / 217);
mainWindowController.refreshplayBtnPosition();
// call only if there is enough space for a new row
if (mainWindowController.getOldXPosHelper() != xPosHelperMax) {
mainWindowController.refreshUIData();
}
// if saveTask is already running kill it // if saveTask is already running kill it
if (saveTask != null) saveTask.cancel(); if (saveTask != null) saveTask.cancel();
@ -227,8 +238,7 @@ public class Main extends Application {
saveTask = new TimerTask() { saveTask = new TimerTask() {
@Override @Override
public void run() { public void run() {
XMLController.setWindowWidth(mainWindowController.getMainAnchorPane().getWidth()); mainWindowController.saveSettings();
xmlController.saveSettings();
} }
}; };
timer.schedule(saveTask, delayTime); timer.schedule(saveTask, delayTime);
@ -249,8 +259,7 @@ public class Main extends Application {
saveTask = new TimerTask() { saveTask = new TimerTask() {
@Override @Override
public void run() { public void run() {
XMLController.setWindowHeight(mainWindowController.getMainAnchorPane().getHeight()); mainWindowController.saveSettings();
xmlController.saveSettings();
} }
}; };
timer.schedule(saveTask, delayTime); timer.schedule(saveTask, delayTime);
@ -280,15 +289,23 @@ public class Main extends Application {
primaryStage.maximizedProperty().addListener(maximizeListener); primaryStage.maximizedProperty().addListener(maximizeListener);
} }
public static Main getMain() { public static void main(String[] args) {
return main; // delete old log file and create new
if(osName.equals("Linux")){
System.setProperty("logFilename", userHome + "/cemu_UI/app.log");
File logFile = new File(userHome + "/cemu_UI/app.log");
logFile.delete();
}else{
System.setProperty("logFilename", userHome + "/Documents/cemu_UI/app.log");
File logFile = new File(userHome + "/Documents/cemu_UI/app.log");
logFile.delete();
}
LOGGER = LogManager.getLogger(Main.class.getName());
launch(args);
} }
public CloudController getCloudController() { @Override
return cloudController; public void stop() {
} System.exit(0);
public AnchorPane getPane() {
return pane;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -22,33 +22,29 @@
package com.cemu_UI.application; package com.cemu_UI.application;
import java.io.IOException; import java.io.IOException;
import java.time.Instant;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import com.cemu_UI.controller.CloudController; import com.cemu_UI.controller.dbController;
import com.cemu_UI.controller.DBController;
import com.cemu_UI.controller.XMLController;
import javafx.application.Platform; import javafx.application.Platform;
public class playGame extends Thread { public class playGame extends Thread{
private MainWindowController mainWindowController; MainWindowController mainWindowController;
private DBController dbController; dbController dbController;
private static final Logger LOGGER = LogManager.getLogger(playGame.class.getName()); private static final Logger LOGGER = LogManager.getLogger(playGame.class.getName());
public playGame(MainWindowController m, com.cemu_UI.controller.DBController db) { public playGame(MainWindowController m, com.cemu_UI.controller.dbController db){
mainWindowController = m; mainWindowController = m;
dbController = db; dbController = db;
} }
@Override @Override
public void run() { public void run(){
String selectedGameTitleID = mainWindowController.getSelectedGameTitleID(); String selectedGameTitleID = mainWindowController.getSelectedGameTitleID();
String cemuBin = XMLController.getCemuPath() + "/Cemu.exe"; String executeComand;
String gameExec = "\"" + mainWindowController.getGameExecutePath() + "\"";
long startTime; long startTime;
long endTime; long endTime;
int timePlayedNow; int timePlayedNow;
@ -56,50 +52,51 @@ public class playGame extends Thread {
Process p; Process p;
Platform.runLater(() -> { Platform.runLater(() -> {
mainWindowController.getPrimaryStage().setIconified(true); // minimize cemu_UI mainWindowController.main.primaryStage.setIconified(true);
}); });
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
try { try{
if (System.getProperty("os.name").equals("Linux")) { if(mainWindowController.isFullscreen()){
if(XMLController.isFullscreen()){ if(System.getProperty("os.name").equals("Linux")){
p = new ProcessBuilder("wine", cemuBin, "-f", "-g", gameExec).start(); executeComand = "wine "+mainWindowController.getCemuPath()+"/Cemu.exe -f -g \""+mainWindowController.getGameExecutePath()+"\"";
} else { } else {
p = new ProcessBuilder("wine", cemuBin, "-g", gameExec).start(); executeComand = mainWindowController.getCemuPath()+"\\Cemu.exe -f -g \""+mainWindowController.getGameExecutePath()+"\"";
} }
}else{
if(System.getProperty("os.name").equals("Linux")){
executeComand = "wine "+mainWindowController.getCemuPath()+"/Cemu.exe -g \""+mainWindowController.getGameExecutePath()+"\"";
} else { } else {
if(XMLController.isFullscreen()){ executeComand = mainWindowController.getCemuPath()+"\\Cemu.exe -g \""+mainWindowController.getGameExecutePath()+"\"";
p = new ProcessBuilder(cemuBin, "-f", "-g", gameExec).start();
} else {
p = new ProcessBuilder(cemuBin, "-g", gameExec).start();
} }
} }
LOGGER.info(executeComand);
p.waitFor(); // wait until cemu is closed so we can calculate the played time p = Runtime.getRuntime().exec(executeComand);
p.waitFor();
endTime = System.currentTimeMillis(); endTime = System.currentTimeMillis();
timePlayedNow = (int) Math.floor(((endTime - startTime)/1000/60)); timePlayedNow = (int) Math.floor(((endTime - startTime)/1000/60));
timePlayed = Integer.parseInt(dbController.getTotalPlaytime(selectedGameTitleID))+timePlayedNow; timePlayed = Integer.parseInt(dbController.getTotalPlaytime(selectedGameTitleID))+timePlayedNow;
dbController.setTotalPlaytime(Integer.toString(timePlayed), selectedGameTitleID); dbController.setTotalPlaytime(Integer.toString(timePlayed), selectedGameTitleID);
Platform.runLater(() -> { Platform.runLater(() -> {
if (Integer.parseInt(dbController.getTotalPlaytime(selectedGameTitleID)) > 60) { if(Integer.parseInt(dbController.getTotalPlaytime(selectedGameTitleID)) > 60){
int hoursPlayed = (int) Math.floor(Integer.parseInt(dbController.getTotalPlaytime(selectedGameTitleID)) / 60); int hoursPlayed = (int) Math.floor(Integer.parseInt(dbController.getTotalPlaytime(selectedGameTitleID))/60);
int minutesPlayed = Integer.parseInt(dbController.getTotalPlaytime(selectedGameTitleID)) - 60 * hoursPlayed; int minutesPlayed = Integer.parseInt(dbController.getTotalPlaytime(selectedGameTitleID))-60*hoursPlayed;
mainWindowController.totalPlaytimeBtn.setText(hoursPlayed + "h " + minutesPlayed + "min"); mainWindowController.totalPlaytimeBtn.setText(hoursPlayed+"h "+minutesPlayed+"min");
} else { }else{
mainWindowController.totalPlaytimeBtn.setText(dbController.getTotalPlaytime(selectedGameTitleID) + " min"); mainWindowController.totalPlaytimeBtn.setText(dbController.getTotalPlaytime(selectedGameTitleID)+ " min");
} }
mainWindowController.getPrimaryStage().setIconified(false); // maximize cemu_UI mainWindowController.main.primaryStage.setIconified(false);
}); });
// System.out.println(mainWindowController.getCemuPath()+"/mlc01/emulatorSave/"+);
//sync savegame with cloud service //sync savegame with cloud service
if (XMLController.isCloudSync()) { if(mainWindowController.isCloudSync()) {
XMLController.setLastLocalSync(Instant.now().getEpochSecond()); mainWindowController.main.cloudController.sync(mainWindowController.getCloudService(), mainWindowController.getCemuPath());
CloudController.getInstance(mainWindowController).sync(XMLController.getCloudService(),
XMLController.getCemuPath(), XMLController.getDirCemuUIPath());
} }
} catch (IOException | InterruptedException e) { }catch (IOException | InterruptedException e){
LOGGER.error(e); e.printStackTrace();
} }
} }

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -22,51 +22,31 @@
package com.cemu_UI.controller; package com.cemu_UI.controller;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.time.Instant;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import com.cemu_UI.application.MainWindowController; import com.cemu_UI.application.MainWindowController;
import com.cemu_UI.datatypes.GlobalDataTypes.CloudService;
import com.cemu_UI.vendorCloudController.GoogleDriveController; import com.cemu_UI.vendorCloudController.GoogleDriveController;
import javafx.application.Platform; import javafx.application.Platform;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
public class CloudController { public class CloudController {
// TODO make singleton
private MainWindowController mwc;
private static CloudController instance = null;
private XMLController xmlController = new XMLController();
private GoogleDriveController googleDriveController = new GoogleDriveController();
private static final Logger LOGGER = LogManager.getLogger(CloudController.class.getName());
public CloudController(MainWindowController mwc) { public CloudController(MainWindowController mwc) {
this.mwc = mwc; this.mwc = mwc;
} }
public static CloudController getInstance(MainWindowController mwc) { private MainWindowController mwc;
if (instance == null) { private GoogleDriveController googleDriveController = new GoogleDriveController();
instance = new CloudController(mwc); private static final Logger LOGGER = LogManager.getLogger(CloudController.class.getName());
}
return instance; public boolean initializeConnection(String cloudService, String cemuDirectory) {
}
public boolean initializeConnection(CloudService cloudService, String cemuDirectory) {
boolean success = false; boolean success = false;
LOGGER.info("sartting cloud initialisation ..."); LOGGER.info("sartting cloud initialisation ...");
if(cloudService == CloudService.GoogleDrive) { if(cloudService.equals("GoogleDrive")) {
LOGGER.info("selected service is Google Drive"); LOGGER.info("selected service is Google Drive");
try { try {
googleDriveController.main(cemuDirectory); googleDriveController.main(cemuDirectory);
@ -77,151 +57,124 @@ public class CloudController {
success = true; success = true;
} }
if(cloudService == CloudService.Dropbox) { if(cloudService.equals("Dropbox")) {
LOGGER.info("selected service is Dropbox"); LOGGER.info("selected service is Dropbox");
} }
LOGGER.info("cloud initialisation done!"); LOGGER.info("cloud initialisation done!");
return success; return success;
} }
/** public void stratupCheck(String cloudService, String cemuDirectory) {
* to trigger a new sync set the mwc LastLocalSync to the actual time and call the sync method if(cloudService.equals("GoogleDrive")) {
* @param cloudService LOGGER.info("starting startup check google drive ...");
* @param cemuDirectory try {
* @param cemu_UIDirectory if (!googleDriveController.checkFolder()) {
*/ googleDriveController.creatFolder();
public void sync(CloudService cloudService, String cemuDirectory, String cemu_UIDirectory) { mwc.saveSettings();
// running sync in a new thread, instead of blocking the main thread
Thread thread = new Thread(new Runnable() { Thread thread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
try {
Platform.runLater(() -> { Platform.runLater(() -> {
mwc.getPlayBtn().setDisable(true); mwc.getPlayBtn().setText("syncing...");
});
googleDriveController.uploadAllFiles();
Platform.runLater(() -> {
mwc.getPlayBtn().setText("play");
});
}
});
thread.start();
} else {
sync(cloudService, cemuDirectory);
}
} catch (IOException e) {
LOGGER.error("google drive startup check failed", e);
}
}
if(cloudService.equals("Dropbox")) {
}
}
public void sync(String cloudService, String cemuDirectory) {
//running sync in a new thread, instead of blocking the main thread
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Platform.runLater(() -> {
mwc.getPlayBtn().setText("syncing..."); mwc.getPlayBtn().setText("syncing...");
}); });
LOGGER.info("starting synchronization in new thread ..."); LOGGER.info("starting synchronization in new thread ...");
// zip the saves folder if(cloudService.equals("GoogleDrive")) {
File zipFile = zipSavegames(cemu_UIDirectory, cemuDirectory); try {
googleDriveController.sync(cemuDirectory);
// upload the zip } catch (IOException e) {
switch (cloudService) { LOGGER.error("google drive synchronization failed", e);
// use GoogleDriveController
case GoogleDrive:
LOGGER.info("using GoogleDriveController");
long lastCloudSync = googleDriveController.getLastCloudSync();
if (!googleDriveController.checkFolder()) {
LOGGER.info("cloud sync folder dosen't exist, creating one!");
googleDriveController.creatFolder();
googleDriveController.uploadZipFile(zipFile);
} else if (XMLController.getLastLocalSync() > lastCloudSync) {
LOGGER.info("local is new, going to upload zip");
googleDriveController.uploadZipFile(zipFile);
} else if (XMLController.getLastLocalSync() < lastCloudSync) {
LOGGER.info("cloud is new, going to download zip");
unzipSavegames(cemuDirectory, googleDriveController.downloadZipFile(cemu_UIDirectory));
XMLController.setLastLocalSync(lastCloudSync);
break;
} else {
LOGGER.info("nothing to do");
break;
} }
XMLController.setLastLocalSync(Long.parseLong(zipFile.getName().substring(0, zipFile.getName().length() - 4))); // set time of last sucessfull sync
break;
case Dropbox:
// do the thing
break;
default:
LOGGER.warn("no cloud vendor found!");
break;
} }
if(cloudService.equals("Dropbox")) {
zipFile.delete(); // delete zipfile in cem_UI directory }
Platform.runLater(() -> { Platform.runLater(() -> {
mwc.getPlayBtn().setText("play"); mwc.getPlayBtn().setText("play");
mwc.getPlayBtn().setDisable(false); mwc.saveSettings();
xmlController.saveSettings();
}); });
LOGGER.info("synchronization successful!"); LOGGER.info("synchronization successful!");
} catch (Exception e) {
LOGGER.error(
"There was an error during syncronisation! Please open a new issue on the cemu_UI github page:",
e);
}
} }
}); });
thread.start(); thread.start();
} }
private File zipSavegames(String cemu_UIDirectory, String cemuDirectory) throws Exception { void uploadFile(String cloudService, File file) {
long unixTimestamp = Instant.now().getEpochSecond();
FileOutputStream fos = new FileOutputStream(cemu_UIDirectory + "/" + unixTimestamp + ".zip");
ZipOutputStream zos = new ZipOutputStream(fos);
addDirToZipArchive(zos, new File(cemuDirectory + "/mlc01/usr/save"), null);
zos.flush();
fos.flush();
zos.close();
fos.close();
return new File(cemu_UIDirectory + "/" + unixTimestamp + ".zip");
}
private static void addDirToZipArchive(ZipOutputStream zos, File fileToZip, String parrentDirectoryName) throws Exception { //running uploadFile in a new thread, instead of blocking the main thread
if (fileToZip == null || !fileToZip.exists()) { new Thread() {
return; @Override
} public void run() {
LOGGER.info("starting uploadFile in new thread ...");
String zipEntryName = fileToZip.getName(); if(cloudService.equals("GoogleDrive")) {
if (parrentDirectoryName!=null && !parrentDirectoryName.isEmpty()) {
zipEntryName = parrentDirectoryName + "/" + fileToZip.getName();
}
if (fileToZip.isDirectory()) {
for (File file : fileToZip.listFiles()) {
addDirToZipArchive(zos, file, zipEntryName);
}
} else {
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(fileToZip);
zos.putNextEntry(new ZipEntry(zipEntryName));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
fis.close();
}
}
private void unzipSavegames(String cemuDirectory, File outputFile) {
try { try {
ZipFile zipFile = new ZipFile(outputFile); googleDriveController.uploadFile(file);
zipFile.extractAll(cemuDirectory + "/mlc01/usr"); } catch (IOException e) {
outputFile.delete(); LOGGER.error("google drive uploadFile failed" ,e);
LOGGER.info("unzip successfull");
} catch (ZipException e) {
LOGGER.error("an error occurred during unziping the file!", e);
} }
} }
if(cloudService.equals("Dropbox")) {
}
}
}.start();
}
public String getFolderID(CloudService cloudService) { public String getFolderID(String cloudService) {
String folderID = ""; String folderID = "";
if (cloudService != null) { if (cloudService != null) {
if (cloudService == CloudService.GoogleDrive) { if(cloudService.equals("GoogleDrive")) {
folderID = googleDriveController.getFolderID(); folderID = googleDriveController.getFolderID();
} }
if (cloudService == CloudService.Dropbox) { if(cloudService.equals("Dropbox")) {
} }
} }
return folderID; return folderID;
} }
public void setFolderID(String folderID, String cloudService) {
if (cloudService != null) {
if (cloudService.equals("GoogleDrive")) {
googleDriveController.setFolderID(folderID);
}
if (cloudService.equals("Dropbox")) {
}
}
}
} }

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -46,25 +46,23 @@ import javafx.application.Platform;
public class UpdateController implements Runnable { public class UpdateController implements Runnable {
private MainWindowController mainWindowController; private MainWindowController mainWindowController;
private int buildNumber; private String buildNumber;
private int updateBuildNumber; // tag_name from gitea
private String apiOutput; private String apiOutput;
@SuppressWarnings("unused") private String updateBuildNumber; // tag_name from Github
private String updateName;
@SuppressWarnings("unused")
private String updateChanges;
private String browserDownloadUrl; // update download link private String browserDownloadUrl; // update download link
private String giteaApiRelease = "https://git.mosad.xyz/api/v1/repos/Seil0/cemu_UI/releases"; private String githubApiRelease = "https://api.github.com/repos/Seil0/cemu_UI/releases/latest";
private URL giteaApiUrl; private String githubApiBeta = "https://api.github.com/repos/Seil0/cemu_UI/releases";
private URL githubApiUrl;
private boolean useBeta; private boolean useBeta;
private static final Logger LOGGER = LogManager.getLogger(UpdateController.class.getName()); private static final Logger LOGGER = LogManager.getLogger(UpdateController.class.getName());
/** /**
* updater for cemu_UI, checks for Updates and download it * updater for cemu_UI based on Project HomeFlix checks for Updates and download
* it in case there is one
*/ */
public UpdateController(MainWindowController mwc, String buildNumber, boolean useBeta) { public UpdateController(MainWindowController mwc, String buildNumber, boolean useBeta) {
mainWindowController = mwc; mainWindowController = mwc;
this.buildNumber = Integer.parseInt(buildNumber); this.buildNumber = buildNumber;
this.useBeta = useBeta; this.useBeta = useBeta;
} }
@ -72,13 +70,19 @@ public class UpdateController implements Runnable {
public void run() { public void run() {
LOGGER.info("beta:" + useBeta + "; checking for updates ..."); LOGGER.info("beta:" + useBeta + "; checking for updates ...");
Platform.runLater(() -> { Platform.runLater(() -> {
mainWindowController.getUpdateBtn().setText(XMLController.getLocalBundle().getString("updateBtnChecking")); mainWindowController.getUpdateBtn().setText("checking for updates ...");
}); });
try { try {
giteaApiUrl = new URL(giteaApiRelease);
BufferedReader ina = new BufferedReader(new InputStreamReader(giteaApiUrl.openStream())); if (useBeta) {
githubApiUrl = new URL(githubApiBeta);
} else {
githubApiUrl = new URL(githubApiRelease);
}
// URL githubApiUrl = new URL(githubApiRelease);
BufferedReader ina = new BufferedReader(new InputStreamReader(githubApiUrl.openStream()));
apiOutput = ina.readLine(); apiOutput = ina.readLine();
ina.close(); ina.close();
} catch (IOException e) { } catch (IOException e) {
@ -87,56 +91,64 @@ public class UpdateController implements Runnable {
}); });
} }
if (useBeta) {
JsonArray objectArray = Json.parse("{\"items\": " + apiOutput + "}").asObject().get("items").asArray(); JsonArray objectArray = Json.parse("{\"items\": " + apiOutput + "}").asObject().get("items").asArray();
JsonValue object = objectArray.get(0).asObject(); // set to the latest release as default JsonValue object = objectArray.get(0);
JsonObject objectAsset = object.asObject().get("assets").asArray().get(0).asObject(); JsonArray objectAssets = object.asObject().get("assets").asArray();
for(JsonValue objectIt : objectArray) { updateBuildNumber = object.asObject().getString("tag_name", "");
// TODO note this will download still the pre-release if there's a more recent stable version // updateName = object.asObject().getString("name", "");
if(objectIt.asObject().getBoolean("prerelease", false) == useBeta) { // updateChanges = object.asObject().getString("body", "");
// we found the needed release either beta or not
object = objectIt; for (JsonValue asset : objectAssets) {
objectAsset = objectIt.asObject().get("assets").asArray().get(0).asObject(); browserDownloadUrl = asset.asObject().getString("browser_download_url", "");
break;
}
} }
updateBuildNumber = Integer.parseInt(object.asObject().getString("tag_name", "")); } else {
updateName = object.asObject().getString("name", ""); JsonObject object = Json.parse(apiOutput).asObject();
updateChanges = object.asObject().getString("body", ""); JsonArray objectAssets = Json.parse(apiOutput).asObject().get("assets").asArray();
updateBuildNumber = object.getString("tag_name", "");
// updateName = object.getString("name", "");
// updateChanges = object.getString("body", "");
for (JsonValue asset : objectAssets) {
browserDownloadUrl = asset.asObject().getString("browser_download_url", "");
}
}
LOGGER.info("Build: " + buildNumber + ", Update: " + updateBuildNumber); LOGGER.info("Build: " + buildNumber + ", Update: " + updateBuildNumber);
/** // Compares the program BuildNumber with the current BuildNumber if program
* Compare the program BuildNumber with the current BuildNumber // BuildNumber < current BuildNumber then perform a update
* if buildNumber < updateBuildNumber then perform a update int iversion = Integer.parseInt(buildNumber);
*/ int iaktVersion = Integer.parseInt(updateBuildNumber.replace(".", ""));
if (buildNumber >= updateBuildNumber) {
if (iversion >= iaktVersion) {
Platform.runLater(() -> { Platform.runLater(() -> {
mainWindowController.getUpdateBtn().setText(XMLController.getLocalBundle().getString("updateBtnNoUpdateAvailable")); mainWindowController.getUpdateBtn().setText("no update available");
}); });
LOGGER.info("no update available"); LOGGER.info("no update available");
} else { } else {
Platform.runLater(() -> { Platform.runLater(() -> {
mainWindowController.getUpdateBtn().setText(XMLController.getLocalBundle().getString("updateBtnUpdateAvailable")); mainWindowController.getUpdateBtn().setText("update available");
}); });
LOGGER.info("update available"); LOGGER.info("update available");
browserDownloadUrl = objectAsset.getString("browser_download_url", "");
LOGGER.info("download link: " + browserDownloadUrl); LOGGER.info("download link: " + browserDownloadUrl);
try { try {
// open new Http connection, ProgressMonitorInputStream for downloading the data // open new Http connection, ProgressMonitorInputStream for downloading the data
HttpURLConnection connection = (HttpURLConnection) new URL(browserDownloadUrl).openConnection(); HttpURLConnection conn = (HttpURLConnection) new URL(browserDownloadUrl).openConnection();
ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(null, "Downloading...", connection.getInputStream()); ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(null, "Downloading...", conn.getInputStream());
ProgressMonitor pm = pmis.getProgressMonitor(); ProgressMonitor pm = pmis.getProgressMonitor();
pm.setMillisToDecideToPopup(0); pm.setMillisToDecideToPopup(0);
pm.setMillisToPopup(0); pm.setMillisToPopup(0);
pm.setMinimum(0);// set beginning of the progress bar to 0 pm.setMinimum(0);// tell the progress bar that we start at the beginning of the stream
pm.setMaximum(connection.getContentLength());// set the end to the file length pm.setMaximum(conn.getContentLength());// tell the progress bar the total number of bytes we are going to read.
FileUtils.copyInputStreamToFile(pmis, new File("cemu_UI_update.jar")); // download update FileUtils.copyInputStreamToFile(pmis, new File("cemu_UI_update.jar")); // download update
org.apache.commons.io.FileUtils.copyFile(new File("cemu_UI_update.jar"), new File("cemu_UI.jar")); org.apache.commons.io.FileUtils.copyFile(new File("cemu_UI_update.jar"), new File("cemu_UI.jar")); // TODO rename update to old name
org.apache.commons.io.FileUtils.deleteQuietly(new File("cemu_UI_update.jar")); // delete update org.apache.commons.io.FileUtils.deleteQuietly(new File("cemu_UI_update.jar")); // delete update
new ProcessBuilder("java", "-jar", "cemu_UI.jar").start(); // start the new application Runtime.getRuntime().exec("java -jar cemu_UI.jar"); // start again
System.exit(0); // close the current application System.exit(0); // finishes itself
} catch (IOException e) { } catch (IOException e) {
Platform.runLater(() -> { Platform.runLater(() -> {
LOGGER.info("could not download update files", e); LOGGER.info("could not download update files", e);

View File

@ -1,419 +0,0 @@
/**
* cemu_UI
*
* Copyright 2017-2019 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.cemu_UI.datatypes.GlobalDataTypes.CloudService;
public class XMLController {
private static final String userHome = System.getProperty("user.home");
private static final String userName = System.getProperty("user.name");
private static final String osName = System.getProperty("os.name");
private static final String osArch = System.getProperty("os.arch");
private static final String osVers = System.getProperty("os.version");
private static final String javaVers = System.getProperty("java.version");
private static final String javaVend = System.getProperty("java.vendor");
private static final String sysLocal = System.getProperty("user.language") + "_" + System.getProperty("user.country");
private static String dirCemuUIPath;
private static File dirCemuUI;
private static File configFile;
private static File gamesDBFile;
private static File reference_gamesFile;
private static File pictureCache;
// user settings
private static String color = "00a8cc";
private static String usrLocal = sysLocal;
private static boolean autoUpdate = false;
private static boolean useBeta = false;
private static boolean fullscreen = false;
private static boolean cloudSync = false;
private static ResourceBundle localBundle = ResourceBundle.getBundle("locals.cemu_UI-Local", Locale.US);
private static String cemuPath;
private static String romDirectoryPath;
private static String folderID;
private static CloudService cloudService;
private static long lastLocalSync;
private static double windowWidth;
private static double windowHeight;
private static final Logger LOGGER = LogManager.getLogger(XMLController.class.getName());
private Properties props = new Properties();
public XMLController() {
if (osName.contains("Windows")) {
dirCemuUIPath = userHome + "/Documents/cemu_UI";
} else {
dirCemuUIPath = userHome + "/cemu_UI";
}
// set the concrete files
dirCemuUI = new File(dirCemuUIPath);
configFile = new File(dirCemuUI + "/config.xml");
gamesDBFile = new File(dirCemuUI + "/games.db");
reference_gamesFile = new File(dirCemuUI + "/reference_games.db");
pictureCache= new File(dirCemuUI+"/picture_cache");
}
/**
* save settings to the config.xml file
*/
public void saveSettings() {
LOGGER.info("saving Settings ...");
try {
props.setProperty("cemuPath", getCemuPath());
props.setProperty("romPath", getRomDirectoryPath());
props.setProperty("color", getColor());
props.setProperty("language", getUsrLocal());
props.setProperty("fullscreen", String.valueOf(isFullscreen()));
props.setProperty("cloudSync", String.valueOf(isCloudSync()));
props.setProperty("autoUpdate", String.valueOf(isAutoUpdate()));
props.setProperty("useBeta", String.valueOf(isUseBeta()));
if (getCloudService() == null) {
props.setProperty("cloudService", "");
props.setProperty("folderID", "");
props.setProperty("lastLocalSync", "");
} else {
props.setProperty("cloudService", getCloudService().toString());
props.setProperty("folderID", getFolderID());
props.setProperty("lastLocalSync", Long.toString(getLastLocalSync()));
}
props.setProperty("windowWidth", Double.toString(getWindowWidth()));
props.setProperty("windowHeight", Double.toString(getWindowHeight()));
OutputStream outputStream = new FileOutputStream(XMLController.getConfigFile()); // new output-stream
props.storeToXML(outputStream, "cemu_UI settings"); // write new .xml
outputStream.close();
LOGGER.info("saving Settings done!");
} catch (IOException e) {
LOGGER.error("an error occured", e);
}
}
/**
* loading saved settings from the config.xml file
* if a value is not present, default is used instead
*/
public void loadSettings() {
LOGGER.info("loading settings ...");
try {
InputStream inputStream = new FileInputStream(XMLController.getConfigFile());
props.loadFromXML(inputStream); // new input-stream from .xml
try {
setCemuPath(props.getProperty("cemuPath"));
} catch (Exception e) {
LOGGER.error("cloud not load cemuPath", e);
setCemuPath("");
}
try {
setRomDirectoryPath(props.getProperty("romPath"));
} catch (Exception e) {
LOGGER.error("could not load romPath", e);
setRomDirectoryPath("");
}
try {
setColor(props.getProperty("color"));
} catch (Exception e) {
LOGGER.error("could not load color value, setting default instead", e);
setColor("00a8cc");
}
if (props.getProperty("language") == null) {
LOGGER.error("cloud not load language, setting default instead");
setUsrLocal("en_US");
} else {
setUsrLocal(props.getProperty("language"));
}
try {
setFullscreen(Boolean.parseBoolean(props.getProperty("fullscreen")));
} catch (Exception e) {
LOGGER.error("could not load fullscreen, setting default instead", e);
setFullscreen(false);
}
try {
setCloudSync(Boolean.parseBoolean(props.getProperty("cloudSync")));
} catch (Exception e) {
LOGGER.error("could not load cloudSync, setting default instead", e);
setCloudSync(false);
}
try {
setAutoUpdate(Boolean.parseBoolean(props.getProperty("autoUpdate")));
} catch (Exception e) {
LOGGER.error("cloud not load autoUpdate", e);
setAutoUpdate(false);
}
try {
setUseBeta(Boolean.parseBoolean(props.getProperty("useBeta")));
} catch (Exception e) {
LOGGER.error("cloud not load autoUpdate", e);
setUseBeta(false);
}
try {
switch (props.getProperty("cloudService")) {
case "GoogleDrive":
setCloudService(CloudService.GoogleDrive);
break;
case "Dropbox":
setCloudService(CloudService.Dropbox);
break;
default:
break;
}
} catch (Exception e) {
LOGGER.error("could not load cloudSync", e);
setCloudService(null);
}
try {
setFolderID(props.getProperty("folderID"));
} catch (Exception e) {
LOGGER.error("could not load folderID, disable cloud sync. Please contact an developer", e);
setCloudSync(false);
}
try {
setLastLocalSync(Long.parseLong(props.getProperty("lastLocalSync")));
} catch (Exception e) {
LOGGER.error("could not load lastSuccessSync, setting default instead", e);
setLastLocalSync(0);
}
try {
setWindowWidth(Double.parseDouble(props.getProperty("windowWidth")));
} catch (Exception e) {
LOGGER.error("could not load windowWidth, setting default instead", e);
setWindowWidth(904);
}
try {
setWindowHeight(Double.parseDouble(props.getProperty("windowHeight")));
} catch (Exception e) {
LOGGER.error("could not load windowHeight, setting default instead", e);
setWindowHeight(600);
}
inputStream.close();
LOGGER.info("loading settings done!");
} catch (IOException e) {
LOGGER.error("an error occured", e);
}
}
// getters for application variables
public static String getUserHome() {
return userHome;
}
public static String getUserName() {
return userName;
}
public static String getOsName() {
return osName;
}
public static String getOsArch() {
return osArch;
}
public static String getOsVers() {
return osVers;
}
public static String getJavaVers() {
return javaVers;
}
public static String getJavaVend() {
return javaVend;
}
public static String getSysLocal() {
return sysLocal;
}
public static String getDirCemuUIPath() {
return dirCemuUIPath;
}
public static File getDirCemuUI() {
return dirCemuUI;
}
public static File getConfigFile() {
return configFile;
}
public static File getGamesDBFile() {
return gamesDBFile;
}
public static File getRference_gamesFile() {
return reference_gamesFile;
}
public static File getPictureCache() {
return pictureCache;
}
// getters & setters for user settings
public static String getColor() {
return color;
}
public static void setColor(String color) {
XMLController.color = color;
}
public static String getUsrLocal() {
return usrLocal;
}
public static void setUsrLocal(String usrLocal) {
XMLController.usrLocal = usrLocal;
}
public static boolean isAutoUpdate() {
return autoUpdate;
}
public static void setAutoUpdate(boolean autoUpdate) {
XMLController.autoUpdate = autoUpdate;
}
public static boolean isUseBeta() {
return useBeta;
}
public static void setUseBeta(boolean useBeta) {
XMLController.useBeta = useBeta;
}
public static boolean isFullscreen() {
return fullscreen;
}
public static void setFullscreen(boolean fullscreen) {
XMLController.fullscreen = fullscreen;
}
public static boolean isCloudSync() {
return cloudSync;
}
public static void setCloudSync(boolean cloudSync) {
XMLController.cloudSync = cloudSync;
}
public static ResourceBundle getLocalBundle() {
return localBundle;
}
public static void setLocalBundle(ResourceBundle localBundle) {
XMLController.localBundle = localBundle;
}
public static String getCemuPath() {
return cemuPath;
}
public static void setCemuPath(String cemuPath) {
XMLController.cemuPath = cemuPath;
}
public static String getRomDirectoryPath() {
return romDirectoryPath;
}
public static void setRomDirectoryPath(String romDirectoryPath) {
XMLController.romDirectoryPath = romDirectoryPath;
}
public static String getFolderID() {
return folderID;
}
public static void setFolderID(String folderID) {
XMLController.folderID = folderID;
}
public static CloudService getCloudService() {
return cloudService;
}
public static void setCloudService(CloudService cloudService) {
XMLController.cloudService = cloudService;
}
public static long getLastLocalSync() {
return lastLocalSync;
}
public static void setLastLocalSync(long lastLocalSync) {
XMLController.lastLocalSync = lastLocalSync;
}
public static double getWindowWidth() {
return windowWidth;
}
public static void setWindowWidth(double windowWidth) {
XMLController.windowWidth = windowWidth;
}
public static double getWindowHeight() {
return windowHeight;
}
public static void setWindowHeight(double windowHeight) {
XMLController.windowHeight = windowHeight;
}
}

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -28,7 +28,6 @@ import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
@ -46,94 +45,95 @@ import org.apache.logging.log4j.Logger;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import com.cemu_UI.datatypes.UIROMDataType; import com.cemu_UI.application.MainWindowController;
import javafx.collections.FXCollections; public class dbController {
import javafx.collections.ObservableList;
public class DBController { public dbController(MainWindowController m) {
mainWindowController = m;
}
private static DBController instance = null; private MainWindowController mainWindowController;
private ArrayList<String> entries = new ArrayList<>(); private ArrayList<String> entries = new ArrayList<>();
private String DB_PATH_LocalGames; private String DB_PATH_localRoms;
private String DB_PATH_ReverenceGames; private String DB_PATH_games;
private Connection connectionLocal = null; private Connection connection = null;
private Connection connectionReverence = null; private Connection connectionGames = null;
private static final Logger LOGGER = LogManager.getLogger(DBController.class.getName()); private static final Logger LOGGER = LogManager.getLogger(dbController.class.getName());
public DBController() { public void main(){
LOGGER.info("<==========starting loading sql==========>");
} loadRomDatabase();
loadGamesDatabase();
public static DBController getInstance() {
if (instance == null) {
instance = new DBController();
}
return instance;
}
/**
* initialize the {@link DBController} with the database connection check if
* there is a need to create a new database refresh the database
*/
public void init() {
initDatabaseConnection();
createRomDatabase(); createRomDatabase();
loadAllGames();
checkRemoveEntry();
LOGGER.info("<==========finished loading sql==========>");
} }
/** /**
* create a new connection to the HomeFlix.db database * set the path to the localRoms.db file and initialize the connection
* AutoCommit is set to false to prevent some issues, so manual commit is active!
* *
* TODO this should be called LocalGames * TODO this should be called LocalGames
*/ */
private void initDatabaseConnection() { private void loadRomDatabase(){
DB_PATH_LocalGames = XMLController.getDirCemuUI() + "/localRoms.db"; if (System.getProperty("os.name").equals("Linux")) {
DB_PATH_ReverenceGames = XMLController.getRference_gamesFile().getAbsolutePath(); DB_PATH_localRoms = System.getProperty("user.home") + "/cemu_UI/localRoms.db";
}else{
DB_PATH_localRoms = System.getProperty("user.home") + "\\Documents\\cemu_UI" + "\\" + "localRoms.db";
}
try { try {
// create a database connection // create a database connection
connectionLocal = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH_LocalGames); connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH_localRoms);
connectionLocal.setAutoCommit(false); connection.setAutoCommit(false); //AutoCommit to false -> manual commit is active
connectionReverence = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH_ReverenceGames);
connectionReverence.setAutoCommit(false);
} catch (SQLException e) { } catch (SQLException e) {
// if the error message is "out of memory", it probably means no database file is found // if the error message is "out of memory", it probably means no database file is found
LOGGER.error("error while loading the Local- or ReverenceGames database", e); LOGGER.error("error while loading the ROM database", e);
}
LOGGER.info("ROM database loaded successfull");
} }
LOGGER.info("Local- and ReverenceGames database loaded successfull"); /**
* set the path to the localRoms.db file and initialize the connection
*
* games.dbcontains a reverence list to for the automatic detection mode
* TODO this should be called ReferenceGameList the games table should be called reference_games
*/
private void loadGamesDatabase() {
if (System.getProperty("os.name").equals("Linux")) {
DB_PATH_games = System.getProperty("user.home") + "/cemu_UI/games.db";
} else {
DB_PATH_games = System.getProperty("user.home") + "\\Documents\\cemu_UI" + "\\" + "games.db";
} }
try {
// create a database connection
connectionGames = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH_games);
connectionGames.setAutoCommit(false); // AutoCommit to false -> manual commit is active
} catch (SQLException e) {
LOGGER.error("error while loading the games database", e);
}
LOGGER.info("games database loaded successfull");
}
/** /**
* creating the local_roms table in localRoms.db * creating the local_roms table in localRoms.db
* if the table has no entries, call loadRomDirectory * if the table has no entries, call loadRomDirectory
* *
* TODO the local_roms table should be called LocalGames * TODO the local_roms table should be called local_games
*/ */
void createRomDatabase() { void createRomDatabase() {
try { try {
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
stmt.executeUpdate("create table if not exists local_roms (title, coverPath, romPath, titleID, productCode, region, lastPlayed, timePlayed)"); stmt.executeUpdate("create table if not exists local_roms (title, coverPath, romPath, titleID, productCode, region, lastPlayed, timePlayed)");
connectionLocal.commit();
stmt.close(); stmt.close();
connection.commit();
} catch (SQLException e) { } catch (SQLException e) {
LOGGER.error("error while creating local-games database", e); LOGGER.error("error while creating ROM database", e);
} }
}
/**
* refresh database to contain all (new added) games
*/
public void refreshDataBase() {
LOGGER.info("<========== starting refreshing database ==========>");
entries.clear();
try { try {
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms"); ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms");
while (rs.next()) { while (rs.next()) {
entries.add(rs.getString(2)); entries.add(rs.getString(2));
@ -143,80 +143,59 @@ public class DBController {
} catch (SQLException e) { } catch (SQLException e) {
LOGGER.error("error while loading ROMs from ROM database, local_roms table", e); LOGGER.error("error while loading ROMs from ROM database, local_roms table", e);
} }
if (entries.size() == 0) { if (entries.size() == 0) {
loadAllGames(); loadRomDirectory(mainWindowController.getRomPath());
}
} }
LOGGER.info("<========== finished refreshing database ==========>"); // add a Ggame to the database
}
// add a game to the database
public void addGame(String title, String coverPath, String romPath, String titleID, String productCode, String region, String lastPlayed, String timePlayed) throws SQLException{ public void addGame(String title, String coverPath, String romPath, String titleID, String productCode, String region, String lastPlayed, String timePlayed) throws SQLException{
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
stmt.executeUpdate("insert into local_roms values ('"+title+"','"+coverPath+"','"+romPath+"','"+titleID+"'," stmt.executeUpdate("insert into local_roms values ('"+title+"','"+coverPath+"','"+romPath+"','"+titleID+"',"
+ "'"+productCode+"','"+region+"','"+lastPlayed+"','"+timePlayed+"')"); + "'"+productCode+"','"+region+"','"+lastPlayed+"','"+timePlayed+"')");
connectionLocal.commit(); connection.commit();
stmt.close(); stmt.close();
LOGGER.info("added \""+title+"\" to ROM database"); LOGGER.info("added \""+title+"\" to ROM database");
} }
// remove a game from the database
public void removeGame(String titleID) throws SQLException{ public void removeGame(String titleID) throws SQLException{
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
stmt.executeUpdate("delete from local_roms where titleID = '"+titleID+"'"); stmt.executeUpdate("delete from local_roms where titleID = '"+titleID+"'");
connectionLocal.commit(); connection.commit();
stmt.close(); stmt.close();
LOGGER.info("removed \""+titleID+"\" from ROM database"); LOGGER.info("removed \""+titleID+"\" from ROM database");
} }
/** //load all ROMs on startup to the mainWindowController
* load all games from the database to a ObservableList, order entries by title void loadAllGames(){
* @return a ObservableList that contains all local games from the database LOGGER.info("loading all games on startup into the mainWindowController ...");
*/
public ObservableList<UIROMDataType> loadAllGames() {
ObservableList<UIROMDataType> games = FXCollections.observableArrayList();
LOGGER.info("loading all local games from the database ...");
try { try {
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms"); ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms");
while (rs.next()) { while (rs.next()) {
games.add(new UIROMDataType(rs.getString("romPath"), rs.getString("titleID"), rs.getString("title"), mainWindowController.addGame(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4));
rs.getString("coverPath")));
} }
stmt.close(); stmt.close();
rs.close(); rs.close();
} catch (Exception e) { }catch (Exception e){
LOGGER.error("error while loading all local games from the database", e); LOGGER.error("error while loading all games into the mainWindowController", e);
}
} }
return games; //load one single ROM after manual adding into the mainWindowController
} public void loadSingleGame(String titleID){
LOGGER.info("loading a single game (ID: "+titleID+") into the mainWindowController ...");
/**
* load one game from the database
* @param titleID the titleID of the game you wish to get
* @return the game you asked for
*/
public UIROMDataType loadSingleGame(String titleID) {
UIROMDataType game = null;
LOGGER.info("loading a single game (ID: {}) from the database ...", titleID);
try { try {
PreparedStatement ps = connectionLocal.prepareStatement("SELECT * FROM local_roms where titleID = ?"); Statement stmt = connection.createStatement();
ps.setString(1, titleID); ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms where titleID = '"+titleID+"'");
ResultSet rs = ps.executeQuery();
while (rs.next()) { while (rs.next()) {
game = new UIROMDataType(rs.getString("romPath"), rs.getString("titleID"), rs.getString("title"), mainWindowController.addGame(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4));
rs.getString("coverPath"));
} }
stmt.close();
rs.close(); rs.close();
ps.close();
}catch (Exception e){ }catch (Exception e){
LOGGER.error("error while loading a single game into the mainWindowController", e); LOGGER.error("error while loading a single game into the mainWindowController", e);
} }
return game;
} }
/** /**
@ -227,56 +206,62 @@ public class DBController {
File dir = new File(directory); File dir = new File(directory);
File appFile; File appFile;
String[] extensions = new String[] { "rpx", "jsp" }; String[] extensions = new String[] { "rpx", "jsp" };
File pictureCache = XMLController.getPictureCache(); File pictureCache;
String coverPath; String coverPath;
if(System.getProperty("os.name").equals("Linux")){
pictureCache = mainWindowController.getPictureCacheLinux();
}else{
pictureCache = mainWindowController.getPictureCacheWin();
}
try { try {
Statement stmt = connectionReverence.createStatement(); Statement stmt = connectionGames.createStatement();
List<File> files = (List<File>) FileUtils.listFiles(dir, extensions, true); List<File> files = (List<File>) FileUtils.listFiles(dir, extensions, true);
LOGGER.info("<============================== start loading ROM Directory ==============================>");
LOGGER.info("Getting all .rpx files in " + dir.getCanonicalPath()+" including those in subdirectories"); LOGGER.info("Getting all .rpx files in " + dir.getCanonicalPath()+" including those in subdirectories");
// for all files in dir get the app.xml // for all files in dir get the app.xml
for (File file : files) { for (File file : files) {
appFile = new File(file.getParent() + "/app.xml"); if(System.getProperty("os.name").equals("Linux")){
appFile = new File(file.getParent()+"/app.xml");
} else {
appFile = new File(file.getParent()+"\\app.xml");
}
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(appFile); Document document = documentBuilder.parse(appFile);
String title_ID = document.getElementsByTagName("title_id").item(0).getTextContent(); // get titile_ID from app.xml String title_ID = document.getElementsByTagName("title_id").item(0).getTextContent(); //get titile_ID from app.xml
title_ID = title_ID.substring(0, 8) + "-" + title_ID.substring(8, title_ID.length()); title_ID = title_ID.substring(0, 8) + "-" + title_ID.substring(8, title_ID.length());
LOGGER.info("Name: " + file.getName() + "; Title ID: " + title_ID); LOGGER.info("Name: "+file.getName()+"; Title ID: "+title_ID);
ResultSet rs = stmt.executeQuery("SELECT * FROM games WHERE TitleID = '" + title_ID + "';"); ResultSet rs = stmt.executeQuery("SELECT * FROM games WHERE TitleID = '"+title_ID+"';");
// for all elements in the games table check if it's already present, else add it // for all elements in the games table check if it's already present, else add it
while (rs.next()) { while (rs.next()) {
if (checkAddEntry(rs.getString(2))) { if (checkEntry(rs.getString(2))) {
LOGGER.info(rs.getString(2) + ": game already in database"); LOGGER.info(rs.getString(2) + ": game already in database");
} else { }else{
LOGGER.info("adding cover to cache ..."); LOGGER.info("adding cover to cache ...");
BufferedImage originalImage = ImageIO.read(new URL(rs.getString(6)));// change path to where file is located BufferedImage originalImage = ImageIO.read(new URL(rs.getString(6)));//change path to where file is located
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType(); int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
BufferedImage resizeImagePNG = resizeImage(originalImage, type, 400, 600); BufferedImage resizeImagePNG = resizeImage(originalImage, type, 400, 600);
if(System.getProperty("os.name").equals("Linux")) {
ImageIO.write(resizeImagePNG, "png", new File(pictureCache+"/"+rs.getString(3)+".png")); //change path where you want it saved
coverPath = pictureCache+"/"+rs.getString(3)+".png";
} else {
ImageIO.write(resizeImagePNG, "png", new File(pictureCache+"\\"+rs.getString(3)+".png")); //change path where you want it saved
coverPath = pictureCache+"\\"+rs.getString(3)+".png";
}
ImageIO.write(resizeImagePNG, "png", new File(pictureCache + "/" + rs.getString(3) + ".png"));
coverPath = pictureCache + "/" + rs.getString(3) + ".png";
LOGGER.info(rs.getString(2) + ": adding ROM"); LOGGER.info(rs.getString(2) + ": adding ROM");
addGame(rs.getString(2), coverPath, file.getCanonicalPath(), rs.getString(1), rs.getString(3), addGame(rs.getString(2), coverPath, file.getCanonicalPath(), rs.getString(1), rs.getString(3), rs.getString(5),"","0");
rs.getString(5), "", "0");
} }
} }
} }
LOGGER.info("<============================= finished loading ROM Directory ============================>");
} catch (IOException | SQLException | ParserConfigurationException | SAXException e) { } catch (IOException | SQLException | ParserConfigurationException | SAXException e) {
LOGGER.error("error while loading ROMs from directory", e); LOGGER.error("error while loading ROMs from directory", e);
} }
} }
/** private boolean checkEntry(String title) throws SQLException{
* check if there is a game with the given name already in the database Statement stmt = connection.createStatement();
* @param title game title
* @return true if the game exists, false if not
* @throws SQLException
*/
private boolean checkAddEntry(String title) throws SQLException{
Statement stmt = connectionLocal.createStatement();
boolean check = false; boolean check = false;
ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms WHERE title = '"+title+"';"); ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms WHERE title = '"+title+"';");
while (rs.next()) { while (rs.next()) {
@ -285,7 +270,6 @@ public class DBController {
return check; return check;
} }
@SuppressWarnings("unused")
private void checkRemoveEntry() { private void checkRemoveEntry() {
/** /**
* TODO needs to be implemented! * TODO needs to be implemented!
@ -294,6 +278,15 @@ public class DBController {
//LOGGER.info("check if entry removed not done yet!"); //LOGGER.info("check if entry removed not done yet!");
} }
private static BufferedImage resizeImage(BufferedImage originalImage, int type, int IMG_WIDTH, int IMG_HEIGHT) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
return resizedImage;
}
/** /**
* getting info for a game with titleID * getting info for a game with titleID
* @param titleID Title-ID of the Game * @param titleID Title-ID of the Game
@ -303,7 +296,7 @@ public class DBController {
String[] gameInfo = new String[4]; String[] gameInfo = new String[4];
LOGGER.info("getting game info for titleID: "+titleID+" ..."); LOGGER.info("getting game info for titleID: "+titleID+" ...");
try { try {
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms where titleID = '"+titleID+"'"); ResultSet rs = stmt.executeQuery("SELECT * FROM local_roms where titleID = '"+titleID+"'");
while (rs.next()) { while (rs.next()) {
gameInfo[0] = rs.getString(1);// title gameInfo[0] = rs.getString(1);// title
@ -322,10 +315,10 @@ public class DBController {
public void setGameInfo(String title, String coverPath, String romPath, String titleID){ public void setGameInfo(String title, String coverPath, String romPath, String titleID){
LOGGER.info("setting game info for titleID: "+titleID+" ..."); LOGGER.info("setting game info for titleID: "+titleID+" ...");
try { try {
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
stmt.executeUpdate("UPDATE local_roms SET title = '" + title + "', coverPath = '" + coverPath + "'," stmt.executeUpdate("UPDATE local_roms SET title = '" + title + "', coverPath = '" + coverPath + "',"
+ " romPath = '" + romPath + "' WHERE titleID = '"+titleID+"';"); + " romPath = '" + romPath + "' WHERE titleID = '"+titleID+"';");
connectionLocal.commit(); connection.commit();
stmt.close(); stmt.close();
}catch (Exception e){ }catch (Exception e){
LOGGER.error("error while setting game info", e); LOGGER.error("error while setting game info", e);
@ -334,9 +327,9 @@ public class DBController {
public void setLastPlayed(String titleID){ public void setLastPlayed(String titleID){
try{ try{
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
stmt.executeUpdate("UPDATE local_roms SET lastPlayed=date('now') WHERE titleID = '"+titleID+"';"); stmt.executeUpdate("UPDATE local_roms SET lastPlayed=date('now') WHERE titleID = '"+titleID+"';");
connectionLocal.commit(); connection.commit();
stmt.close(); stmt.close();
}catch(SQLException e){ }catch(SQLException e){
LOGGER.error("failed to set the last played", e); LOGGER.error("failed to set the last played", e);
@ -346,7 +339,7 @@ public class DBController {
public String getLastPlayed(String titleID){ public String getLastPlayed(String titleID){
String lastPlayed = null; String lastPlayed = null;
try{ try{
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT lastPlayed FROM local_roms WHERE titleID = '"+titleID+"';" ); ResultSet rs = stmt.executeQuery("SELECT lastPlayed FROM local_roms WHERE titleID = '"+titleID+"';" );
lastPlayed = rs.getString(1); lastPlayed = rs.getString(1);
stmt.close(); stmt.close();
@ -359,9 +352,9 @@ public class DBController {
public void setTotalPlaytime(String timePlayed, String titleID){ public void setTotalPlaytime(String timePlayed, String titleID){
try{ try{
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
stmt.executeUpdate("UPDATE local_roms SET timePlayed='"+timePlayed+"' WHERE titleID = '"+titleID+"';"); stmt.executeUpdate("UPDATE local_roms SET timePlayed='"+timePlayed+"' WHERE titleID = '"+titleID+"';");
connectionLocal.commit(); connection.commit();
stmt.close(); stmt.close();
}catch(SQLException e){ }catch(SQLException e){
LOGGER.error("failed to set total play time", e); LOGGER.error("failed to set total play time", e);
@ -372,7 +365,7 @@ public class DBController {
public String getTotalPlaytime(String titleID){ public String getTotalPlaytime(String titleID){
String timePlayed = null; String timePlayed = null;
try{ try{
Statement stmt = connectionLocal.createStatement(); Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT timePlayed FROM local_roms WHERE titleID = '"+titleID+"';" ); ResultSet rs = stmt.executeQuery("SELECT timePlayed FROM local_roms WHERE titleID = '"+titleID+"';" );
timePlayed = rs.getString(1); timePlayed = rs.getString(1);
stmt.close(); stmt.close();
@ -383,13 +376,5 @@ public class DBController {
return timePlayed; return timePlayed;
} }
private static BufferedImage resizeImage(BufferedImage originalImage, int type, int IMG_WIDTH, int IMG_HEIGHT) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
return resizedImage;
}
} }

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -1,29 +0,0 @@
/**
* cemu_UI
*
* Copyright 2017-2019 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.datatypes;
public class GlobalDataTypes {
public enum CloudService {
GoogleDrive, Dropbox
}
}

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -21,111 +21,107 @@
package com.cemu_UI.datatypes; package com.cemu_UI.datatypes;
import java.io.File;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import javafx.geometry.Insets; import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.ContextMenu; import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
public class UIROMDataType extends VBox { public class UIROMDataType {
private String romPath; private final SimpleObjectProperty<VBox> vBox = new SimpleObjectProperty<>();
private String titleID; private final SimpleObjectProperty<Label> label = new SimpleObjectProperty<>();
private String name; private final SimpleObjectProperty<JFXButton> button = new SimpleObjectProperty<>();
private Label label = new Label(); private final SimpleObjectProperty<ImageView> imageView = new SimpleObjectProperty<>();
private JFXButton button = new JFXButton(); private final StringProperty titleID = new SimpleStringProperty();
private ImageView imageView = new ImageView(); private final StringProperty romPath = new SimpleStringProperty();
public UIROMDataType(String romPath, String titleID, String name, String coverPath) { /**
this(); * Data type used for UI ROM elements all uiROMElemts are of this data type
*/
this.romPath = romPath; public UIROMDataType (final VBox vBox, final Label label, final JFXButton button, final ImageView imageView, final String titleID, final String romPath){
this.titleID = titleID; this.vBox.set(vBox);
this.name = name; this.label.set(label);
this.button.set(button);
label.setText(name); this.imageView.set(imageView);
imageView.setImage(new Image(new File(coverPath).toURI().toString())); this.titleID.set(titleID);
this.romPath.set(romPath);
} }
public UIROMDataType(String romPath, String titleID, String name, String coverPath, ContextMenu contextMenu) { public SimpleObjectProperty<VBox> vBoxProperty(){
this(); return vBox;
this.romPath = romPath;
this.titleID = titleID;
this.name = name;
label.setText(name);
imageView.setImage(new Image(new File(coverPath).toURI().toString()));
button.setContextMenu(contextMenu);
} }
public UIROMDataType() { public SimpleObjectProperty<Label> labelProperty(){
super.getChildren().addAll(label, button);
label.setMaxWidth(200);
label.setPadding(new Insets(0,0,0,8));
label.setFont(Font.font("System", FontWeight.BOLD, 14));
imageView.setFitHeight(300);
imageView.setFitWidth(200);
button.setStyle("-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.8), 10, 0, 0, 3); ");
button.setGraphic(imageView);
}
public String getRomPath() {
return romPath;
}
public String getTitleID() {
return titleID;
}
public String getName() {
return name;
}
public Label getLabel() {
return label; return label;
} }
public JFXButton getButton() { public SimpleObjectProperty<JFXButton> buttonProperty(){
return button; return button;
} }
public ImageView getImageView() { public SimpleObjectProperty<ImageView> imageViewProperty(){
return imageView; return imageView;
} }
public void setRomPath(String romPath) { public StringProperty titleIDProperty(){
this.romPath = romPath; return titleID;
} }
public void setTitleID(String titleID) { public StringProperty romPathProperty(){
this.titleID = titleID; return romPath;
} }
public void setName(String name) {
this.name = name; public final VBox getVBox() {
return vBoxProperty().get();
} }
public void setLabel(Label label) { public final Label getLabel() {
this.label = label; return labelProperty().get();
} }
public void setButton(JFXButton button) { public final JFXButton getButton() {
this.button = button; return buttonProperty().get();
} }
public void setImageView(ImageView imageView) { public final ImageView getImageView() {
this.imageView = imageView; return imageViewProperty().get();
} }
public final String getTitleID(){
return titleIDProperty().get();
}
public final String getRomPath(){
return romPathProperty().get();
}
public final void setVBox(VBox vBox) {
vBoxProperty().set(vBox);
}
public final void setLabel(Label label) {
labelProperty().set(label);
}
public final void setButton(JFXButton button) {
buttonProperty().set(button);
}
public final void setImageView(ImageView imageView) {
imageViewProperty().set(imageView);
}
public final void setTitleID(String titleID){
titleIDProperty().set(titleID);
}
public final void setRomPath(String romPath){
romPathProperty().set(romPath);
}
} }

View File

@ -1,250 +0,0 @@
/**
* cemu_UI
*
* Copyright 2017-2019 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.uiElements;
import java.io.File;
import com.cemu_UI.application.MainWindowController;
import com.cemu_UI.controller.XMLController;
import com.jfoenix.controls.JFXAlert;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialogLayout;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class JFXEditGameAlert {
private String headingText;
private String bodyText;
private String title = "";
private String coverPath = "";
private String romPath = "";
private String titleID = "";
private String btnStyle;
private int mode;
private Stage stage;
private MainWindowController mwc; // TODO remove this!
/**
* Creates a new JFoenix Alert to show some information with okay and cancel option
* @param headingText Heading text of the alert
* @param bodyText Content text of the alert
* @param btnStyle Style of the buttons
* @param mode Set to 0 for add and 1 for edit mode
* @param stage Stage to which the Alert belongs
* @param mwc a mwc dep, it's horrible i know
*/
public JFXEditGameAlert(String headingText, String bodyText, String btnStyle, int mode, Stage stage, MainWindowController mwc) {
this.headingText = headingText;
this.bodyText = bodyText;
this.btnStyle = btnStyle;
this.mode = mode;
this.stage = stage;
this.mwc = mwc;
}
public void showAndWait( ) {
JFXAlert<Void> alert = new JFXAlert<>(stage);
TextField gameTitleTF = new TextField();
gameTitleTF.setPromptText(XMLController.getLocalBundle().getString("gameTitle"));
TextField gameTitleIDTF = new TextField();
gameTitleIDTF.setPromptText(XMLController.getLocalBundle().getString("titleID"));
TextField romPathTF = new TextField();
romPathTF.setPromptText(XMLController.getLocalBundle().getString("romPath"));
TextField gameCoverTF = new TextField();
gameCoverTF.setPromptText(XMLController.getLocalBundle().getString("coverPath"));
if (mode == 1) {
gameTitleTF.setText(title);
gameTitleIDTF.setText(titleID);
romPathTF.setText(romPath);
gameCoverTF.setText(coverPath);
gameTitleIDTF.setEditable(false);
}
JFXButton okayBtn = new JFXButton(XMLController.getLocalBundle().getString("okayBtnText"));
okayBtn.setOnAction(event -> {
if (romPathTF.getText().toString().length() == 0 || gameCoverTF.getText().toString().length() == 0
|| gameTitleTF.getText().toString().length() == 0
|| gameTitleIDTF.getText().toString().length() == 0) {
// addGame error dialog
JFXInfoAlert errorDialog = new JFXInfoAlert(
XMLController.getLocalBundle().getString("editGameDialogHeadingTextError"),
XMLController.getLocalBundle().getString("editGameDialogBodyTextError"), btnStyle, stage);
errorDialog.showAndWait();
} else {
switch (mode) {
case 0:
// add-mode title, coverPath, romPath, titleID
mwc.addBtnReturn(gameTitleTF.getText().toString(), gameCoverTF.getText().toString(),
romPathTF.getText().toString(), gameTitleIDTF.getText().toString());
break;
case 1:
// edit mode
mwc.editBtnReturn(gameTitleTF.getText().toString(), gameCoverTF.getText().toString(),
romPathTF.getText().toString(), gameTitleIDTF.getText().toString());
break;
default:
break;
}
alert.close();
}
});
okayBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
okayBtn.setPrefHeight(32);
okayBtn.setStyle(btnStyle);
JFXButton cancelBtn = new JFXButton(XMLController.getLocalBundle().getString("cancelBtnText"));
cancelBtn.addEventHandler(ActionEvent.ACTION, (e)-> alert.close());
cancelBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
cancelBtn.setPrefHeight(32);
cancelBtn.setStyle(btnStyle);
JFXButton selectPathBtn = new JFXButton(XMLController.getLocalBundle().getString("editGameDialogSelectPathBtn"));
selectPathBtn.setPrefWidth(110);
selectPathBtn.setStyle(btnStyle);
selectPathBtn.setOnAction(event -> {
FileChooser romDirectoryChooser = new FileChooser();
File romDirectory = romDirectoryChooser.showOpenDialog(stage);
romPathTF.setText(romDirectory.getAbsolutePath());
});
JFXButton selectCoverBtn = new JFXButton(XMLController.getLocalBundle().getString("editGameDialogSelectCoverBtn"));
selectCoverBtn.setPrefWidth(110);
selectCoverBtn.setStyle(btnStyle);
selectCoverBtn.setOnAction(event -> {
FileChooser coverDirectoryChooser = new FileChooser();
File coverDirectory = coverDirectoryChooser.showOpenDialog(stage);
gameCoverTF.setText(coverDirectory.getAbsolutePath());
});
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(15, 10, 10, 10));
grid.add(new Label(XMLController.getLocalBundle().getString("gameTitle") + ":"), 0, 0);
grid.add(gameTitleTF, 1, 0);
grid.add(new Label(XMLController.getLocalBundle().getString("titleID") + ":"), 0, 1);
grid.add(gameTitleIDTF, 1, 1);
grid.add(new Label(XMLController.getLocalBundle().getString("romPath") + ":"), 0, 2);
grid.add(romPathTF, 1, 2);
grid.add(selectPathBtn, 2, 2);
grid.add(new Label(XMLController.getLocalBundle().getString("coverPath") + ":"), 0, 3);
grid.add(gameCoverTF, 1, 3);
grid.add(selectCoverBtn, 2, 3);
VBox vbox = new VBox();
vbox.getChildren().addAll(new Text(bodyText), grid);
JFXDialogLayout content = new JFXDialogLayout();
content.setActions(cancelBtn, okayBtn);
content.setHeading(new Text(headingText));
content.setBody(vbox);
alert.setContent(content);
alert.showAndWait();
}
public String getHeadingText() {
return headingText;
}
public String getBodyText() {
return bodyText;
}
public String getTitle() {
return title;
}
public String getCoverPath() {
return coverPath;
}
public String getRomPath() {
return romPath;
}
public String getTitleID() {
return titleID;
}
public String getBtnStyle() {
return btnStyle;
}
public int getMode() {
return mode;
}
public Stage getStage() {
return stage;
}
public void setHeadingText(String headingText) {
this.headingText = headingText;
}
public void setBodyText(String bodyText) {
this.bodyText = bodyText;
}
public void setTitle(String title) {
this.title = title;
}
public void setCoverPath(String coverPath) {
this.coverPath = coverPath;
}
public void setRomPath(String romPath) {
this.romPath = romPath;
}
public void setTitleID(String titleID) {
this.titleID = titleID;
}
public void setBtnStyle(String btnStyle) {
this.btnStyle = btnStyle;
}
public void setMode(int mode) {
this.mode = mode;
}
public void setStage(Stage stage) {
this.stage = stage;
}
}

View File

@ -0,0 +1,233 @@
/**
* cemu_UI
*
* Copyright 2017 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.uiElements;
import java.io.File;
import com.cemu_UI.application.MainWindowController;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialogLayout;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class JFXEditGameDialog {
private String headingText;
private String bodyText;
private String dialogBtnStyle;
private String title = "";
private String coverPath = "";
private String romPath = "";
private String titleID = "";
private int dialogWidth;
private int dialogHeight;
private int mode;
private Stage stage;
private Pane pane;
private MainWindowController mwc;
/**
* Creates a new JFoenix Dialog to show some information with okay and cancel option
* @param headingText Heading Text, just the heading
* @param bodyText body Text, all other text belongs here
* @param dialogBtnStyle Style of the okay button
* @param dialogWidth dialog width
* @param dialogHeight dialog height
* @param mode set to 0 for add and 1 for edit mode
* @param stage the primary stage
* @param pane pane to which the dialog belongs
*/
public JFXEditGameDialog(String headingText, String bodyText, String dialogBtnStyle, int dialogWidth,
int dialogHeight, int mode, MainWindowController mwc, Stage stage, Pane pane) {
this.headingText = headingText;
this.bodyText = bodyText;
this.dialogBtnStyle = dialogBtnStyle;
this.dialogWidth = dialogWidth;
this.dialogHeight = dialogHeight;
this.mode = mode;
this.mwc = mwc;
this.stage = stage;
this.pane = pane;
}
public void show() {
JFXDialogLayout content = new JFXDialogLayout();
StackPane stackPane = new StackPane();
stackPane.autosize();
JFXDialog dialog = new JFXDialog(stackPane, content, JFXDialog.DialogTransition.LEFT, true);
Label placeholder = new Label();
placeholder.setPrefSize(15, 10);
TextField gameTitleTF = new TextField();
gameTitleTF.setPromptText("game tile");
TextField gameTitleIDTF = new TextField();
gameTitleIDTF.setPromptText("title ID");
TextField romPathTF = new TextField();
romPathTF.setPromptText("ROM path");
TextField gameCoverTF = new TextField();
gameCoverTF.setPromptText("cover path");
if (mode == 1) {
gameTitleTF.setText(title);
gameTitleIDTF.setText(titleID);
romPathTF.setText(romPath);
gameCoverTF.setText(coverPath);
gameTitleIDTF.setEditable(false);
}
JFXButton okayBtn = new JFXButton("Okay");
okayBtn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
if (romPathTF.getText().toString().length() == 0 || gameCoverTF.getText().toString().length() == 0
|| gameTitleTF.getText().toString().length() == 0 || gameTitleIDTF.getText().toString().length() == 0) {
// LOGGER.info("No parameter set!");
// addGame error dialog
String headingTextError = "Error while adding a new Game!";
String bodyTextError = "There was some truble adding your game."
+ "\nOne of the needed values was empty, please try again to add your game.";
JFXInfoDialog errorDialog = new JFXInfoDialog(headingTextError, bodyTextError, dialogBtnStyle, 350,170, pane);
errorDialog.show();
} else {
switch (mode) {
case 0:
// add-mode title, coverPath, romPath, titleID
mwc.addBtnReturn(gameTitleTF.getText().toString(), gameCoverTF.getText().toString(),
romPathTF.getText().toString(), gameTitleIDTF.getText().toString());
dialog.close();
break;
case 1:
// edit mode
mwc.editBtnReturn(gameTitleTF.getText().toString(), gameCoverTF.getText().toString(),
romPathTF.getText().toString(), gameTitleIDTF.getText().toString());
dialog.close();
break;
default:
dialog.close();
break;
}
}
}
});
okayBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
okayBtn.setPrefHeight(32);
okayBtn.setStyle(dialogBtnStyle);
JFXButton cancelBtn = new JFXButton("Cancel");
cancelBtn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
dialog.close();
}
});
cancelBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
cancelBtn.setPrefHeight(32);
cancelBtn.setStyle(dialogBtnStyle);
JFXButton selectPathBtn = new JFXButton("select .rpx file");
selectPathBtn.setPrefWidth(110);
selectPathBtn.setStyle(dialogBtnStyle);
selectPathBtn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
FileChooser romDirectoryChooser = new FileChooser();
File romDirectory = romDirectoryChooser.showOpenDialog(stage);
romPathTF.setText(romDirectory.getAbsolutePath());
}
});
JFXButton selectCoverBtn = new JFXButton("select cover file");
selectCoverBtn.setPrefWidth(110);
selectCoverBtn.setStyle(dialogBtnStyle);
selectCoverBtn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
FileChooser coverDirectoryChooser = new FileChooser();
File coverDirectory = coverDirectoryChooser.showOpenDialog(stage);
gameCoverTF.setText(coverDirectory.getAbsolutePath());
}
});
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(15, 10, 10, 10));
grid.add(new Label("game title:"), 0, 0);
grid.add(gameTitleTF, 1, 0);
grid.add(new Label("title id:"), 0, 1);
grid.add(gameTitleIDTF, 1, 1);
grid.add(new Label("ROM path:"), 0, 2);
grid.add(romPathTF, 1, 2);
grid.add(selectPathBtn, 2, 2);
grid.add(new Label("cover path:"), 0, 3);
grid.add(gameCoverTF, 1, 3);
grid.add(selectCoverBtn, 2, 3);
Text bdyText = new Text(bodyText);
VBox vbox = new VBox();
vbox.getChildren().addAll(bdyText, grid);
content.setHeading(new Text(headingText));
content.setBody(vbox);
content.setActions(cancelBtn, placeholder, okayBtn);
content.setPrefSize(dialogWidth, dialogHeight);
pane.getChildren().add(stackPane);
AnchorPane.setTopAnchor(stackPane, (pane.getHeight()-content.getPrefHeight())/2);
AnchorPane.setLeftAnchor(stackPane, (pane.getWidth()-content.getPrefWidth())/2);
dialog.show();
}
public void setTitle(String title) {
this.title = title;
}
public void setCoverPath(String coverPath) {
this.coverPath = coverPath;
}
public void setRomPath(String romPath) {
this.romPath = romPath;
}
public void setTitleID(String titleID) {
this.titleID = titleID;
}
}

View File

@ -1,106 +0,0 @@
/**
* cemu_UI
*
* Copyright 2017-2019 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.uiElements;
import com.jfoenix.controls.JFXAlert;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialogLayout;
import javafx.event.ActionEvent;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class JFXInfoAlert {
private String headingText;
private String bodyText;
private String btnStyle;
private Stage stage;
/**
* Creates a new JFoenix Alert to show some information
* @param headerText Heading text of the alert
* @param bodyText Content text of the alert
* @param btnStyle Style of the okay button
* @param stage Stage to which the Alert belongs
*/
public JFXInfoAlert(String headingText, String bodyText, String btnStyle, Stage stage) {
setHeadingText(headingText);
setBodyText(bodyText);
setBtnStyle(btnStyle);
setStage(stage);
}
public JFXInfoAlert() {
// Auto-generated constructor stub
}
public void showAndWait( ) {
JFXAlert<Void> alert = new JFXAlert<>(stage);
JFXButton button = new JFXButton("Okay");
button.addEventHandler(ActionEvent.ACTION, (e)-> alert.close());
button.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
button.setPrefHeight(32);
button.setStyle(btnStyle);
JFXDialogLayout content = new JFXDialogLayout();
content.setActions(button);
content.setHeading(new Text(headingText));
content.setBody(new Text(bodyText));
alert.setContent(content);
alert.showAndWait();
}
public String getHeadingText() {
return headingText;
}
public void setHeadingText(String headingText) {
this.headingText = headingText;
}
public String getBodyText() {
return bodyText;
}
public void setBodyText(String bodyText) {
this.bodyText = bodyText;
}
public String getBtnStyle() {
return btnStyle;
}
public void setBtnStyle(String btnStyle) {
this.btnStyle = btnStyle;
}
public Stage getStage() {
return stage;
}
public void setStage(Stage stage) {
this.stage = stage;
}
}

View File

@ -0,0 +1,86 @@
/**
* cemu_UI
*
* Copyright 2017 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.uiElements;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialogLayout;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
public class JFXInfoDialog {
private String headingText;
private String bodyText;
private String dialogBtnStyle;
private int dialogWidth;
private int dialogHeight;
private Pane pane;
/**
* Creates a new JFoenix Dialog to show some information
* @param headingText Heading Text, just the heading
* @param bodyText body Text, all other text belongs here
* @param dialogBtnStyle Style of the okay button
* @param dialogWidth dialog width
* @param dialogHeight dialog height
* @param pane pane to which the dialog belongs
*/
public JFXInfoDialog(String headingText, String bodyText, String dialogBtnStyle, int dialogWidth, int dialogHeight, Pane pane) {
this.headingText = headingText;
this.bodyText = bodyText;
this.dialogBtnStyle = dialogBtnStyle;
this.dialogWidth = dialogWidth;
this.dialogHeight = dialogHeight;
this.pane = pane;
}
public void show() {
JFXDialogLayout content = new JFXDialogLayout();
content.setHeading(new Text(headingText));
content.setBody(new Text(bodyText));
content.setPrefSize(dialogWidth, dialogHeight);
StackPane stackPane = new StackPane();
stackPane.autosize();
JFXDialog dialog = new JFXDialog(stackPane, content, JFXDialog.DialogTransition.LEFT, true);
JFXButton button = new JFXButton("Okay");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
dialog.close();
}
});
button.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
button.setPrefHeight(32);
button.setStyle(dialogBtnStyle);
content.setActions(button);
pane.getChildren().add(stackPane);
AnchorPane.setTopAnchor(stackPane, (pane.getHeight() - content.getPrefHeight()) / 2);
AnchorPane.setLeftAnchor(stackPane, (pane.getWidth() - content.getPrefWidth()) / 2);
dialog.show();
}
}

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,93 +19,88 @@
* MA 02110-1301, USA. * MA 02110-1301, USA.
*/ */
package com.cemu_UI.uiElements; package com.cemu_UI.uiElements;
import com.cemu_UI.controller.XMLController;
import com.jfoenix.controls.JFXAlert;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialogLayout; import com.jfoenix.controls.JFXDialogLayout;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text; import javafx.scene.text.Text;
import javafx.stage.Stage;
public class JFXOkayCancelAlert { public class JFXOkayCancelDialog {
private String headingText; private String headingText;
private String bodyText; private String bodyText;
private String btnStyle; private String dialogBtnStyle;
private Stage stage; private String okayText = "okay";
private String cancelText = "cancel";
private int dialogWidth;
private int dialogHeight;
private EventHandler<ActionEvent> okayAction; private EventHandler<ActionEvent> okayAction;
private EventHandler<ActionEvent> cancelAction; private EventHandler<ActionEvent> cancelAction;
private Pane pane;
private String okayText = XMLController.getLocalBundle().getString("okayBtnText");
private String cancelText = XMLController.getLocalBundle().getString("cancelBtnText");
/** /**
* * Creates a new JFoenix Dialog to show some information with okay and cancel option
* @param headingText Heading text of the alert * @param headingText Heading Text, just the heading
* @param bodyText Content text of the alert * @param bodyText body Text, all other text belongs here
* @param btnStyle Style of the buttons * @param dialogBtnStyle Style of the okay button
* @param stage Stage to which the Alert belongs * @param dialogWidth dialog width
* @param dialogHeight dialog height
* @param okayAction action which is performed if the okay button is clicked
* @param cancelAction action which is performed if the cancel button is clicked
* @param pane pane to which the dialog belongs
*/ */
public JFXOkayCancelAlert(String headingText, String bodyText, String btnStyle, Stage stage) { public JFXOkayCancelDialog(String headingText, String bodyText, String dialogBtnStyle, int dialogWidth,
setHeadingText(headingText); int dialogHeight, EventHandler<ActionEvent> okayAction, EventHandler<ActionEvent> cancelAction, Pane pane) {
setBodyText(bodyText); this.headingText = headingText;
setBtnStyle(btnStyle); this.bodyText = bodyText;
setStage(stage); this.dialogBtnStyle = dialogBtnStyle;
this.dialogWidth = dialogWidth;
this.dialogHeight = dialogHeight;
this.okayAction = okayAction;
this.cancelAction = cancelAction;
this.pane = pane;
} }
public void showAndWait( ) { public void show() {
JFXAlert<Void> alert = new JFXAlert<>(stage); JFXDialogLayout content = new JFXDialogLayout();
content.setHeading(new Text(headingText));
content.setBody(new Text(bodyText));
StackPane stackPane = new StackPane();
stackPane.autosize();
JFXDialog dialog = new JFXDialog(stackPane, content, JFXDialog.DialogTransition.LEFT, true);
JFXButton okayBtn = new JFXButton(okayText); JFXButton okayBtn = new JFXButton(okayText);
okayBtn.addEventHandler(ActionEvent.ACTION, (e)-> alert.close()); okayBtn.addEventHandler(ActionEvent.ACTION, (e)-> {
dialog.close();
});
okayBtn.addEventHandler(ActionEvent.ACTION, okayAction); okayBtn.addEventHandler(ActionEvent.ACTION, okayAction);
okayBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED); okayBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
okayBtn.setPrefHeight(32); okayBtn.setPrefHeight(32);
okayBtn.setStyle(btnStyle); okayBtn.setStyle(dialogBtnStyle);
JFXButton cancelBtn = new JFXButton(cancelText); JFXButton cancelBtn = new JFXButton(cancelText);
cancelBtn.addEventHandler(ActionEvent.ACTION, (e)-> alert.close()); cancelBtn.addEventHandler(ActionEvent.ACTION, (e)-> {
dialog.close();
});
cancelBtn.addEventHandler(ActionEvent.ACTION, cancelAction); cancelBtn.addEventHandler(ActionEvent.ACTION, cancelAction);
cancelBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED); cancelBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
cancelBtn.setPrefHeight(32); cancelBtn.setPrefHeight(32);
cancelBtn.setStyle(btnStyle); cancelBtn.setStyle(dialogBtnStyle);
Label placeholder = new Label();
placeholder.setPrefSize(15, 10);
JFXDialogLayout content = new JFXDialogLayout(); content.setActions(cancelBtn, placeholder, okayBtn);
content.setActions(cancelBtn, okayBtn); content.setPrefSize(dialogWidth, dialogHeight);
content.setHeading(new Text(headingText)); pane.getChildren().add(stackPane);
content.setBody(new Text(bodyText)); AnchorPane.setTopAnchor(stackPane, (pane.getHeight()-content.getPrefHeight())/2);
alert.setContent(content); AnchorPane.setLeftAnchor(stackPane, (pane.getWidth()-content.getPrefWidth())/2);
alert.showAndWait(); dialog.show();
}
public String getHeadingText() {
return headingText;
}
public void setHeadingText(String headingText) {
this.headingText = headingText;
}
public String getBodyText() {
return bodyText;
}
public void setBodyText(String bodyText) {
this.bodyText = bodyText;
}
public String getBtnStyle() {
return btnStyle;
}
public void setBtnStyle(String btnStyle) {
this.btnStyle = btnStyle;
} }
public String getOkayText() { public String getOkayText() {
@ -124,14 +119,6 @@ public class JFXOkayCancelAlert {
this.cancelText = cancelText; this.cancelText = cancelText;
} }
public Stage getStage() {
return stage;
}
public void setStage(Stage stage) {
this.stage = stage;
}
public EventHandler<ActionEvent> getOkayAction() { public EventHandler<ActionEvent> getOkayAction() {
return okayAction; return okayAction;
} }
@ -149,3 +136,4 @@ public class JFXOkayCancelAlert {
} }
} }

View File

@ -1,104 +0,0 @@
/**
* cemu_UI
*
* Copyright 2017-2019 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.uiElements;
import com.jfoenix.controls.JFXAlert;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialogLayout;
import com.jfoenix.controls.JFXTextArea;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class JFXTextAreaAlert {
private String headingText;
private String textAreaText;
private String btnStyle;
private Stage stage;
/**
* Creates a new JFoenix Alert to show some information on a TextArea
* @param headingText Heading text of the alert
* @param textAreaText Content text of the alert
* @param btnStyle Style of the okay button
* @param stage Stage to which the Alert belongs
*/
public JFXTextAreaAlert(String headingText, String textAreaText, String btnStyle, Stage stage) {
setHeadingText(headingText);
setTextAreaText(textAreaText);
setBtnStyle(btnStyle);
setStage(stage);
}
public void showAndWait( ) {
JFXAlert<Void> alert = new JFXAlert<>(stage);
JFXTextArea textArea = new JFXTextArea(textAreaText);
textArea.setMinWidth(450);
JFXButton button = new JFXButton("Okay");
button.setOnAction(event -> alert.close());
button.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
button.setPrefHeight(32);
button.setStyle(btnStyle);
JFXDialogLayout content = new JFXDialogLayout();
content.setActions(button);
content.setHeading(new Text(headingText));
content.setBody(textArea);
alert.setContent(content);
alert.showAndWait();
}
public String getHeadingText() {
return headingText;
}
public String getTextAreaText() {
return textAreaText;
}
public String getBtnStyle() {
return btnStyle;
}
public Stage getStage() {
return stage;
}
public void setHeadingText(String headingText) {
this.headingText = headingText;
}
public void setTextAreaText(String textAreaText) {
this.textAreaText = textAreaText;
}
public void setBtnStyle(String btnStyle) {
this.btnStyle = btnStyle;
}
public void setStage(Stage stage) {
this.stage = stage;
}
}

View File

@ -0,0 +1,98 @@
/**
* cemu_UI
*
* Copyright 2017 <@Seil0>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.cemu_UI.uiElements;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialogLayout;
import com.jfoenix.controls.JFXTextArea;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
public class JFXTextAreaInfoDialog {
private String headingText;
private String bodyText;
private String dialogBtnStyle;
private int dialogWidth;
private int dialogHeight;
private JFXTextArea textArea;
private Pane pane;
/**
* Creates a new JFoenix Dialog to show some information
* @param headingText Heading Text, just the heading
* @param bodyText body Text, all other text belongs here
* @param dialogBtnStyle Style of the okay button
* @param dialogWidth dialog width
* @param dialogHeight dialog height
* @param pane pane to which the dialog belongs
*/
public JFXTextAreaInfoDialog(String headingText, String bodyText, String dialogBtnStyle, int dialogWidth, int dialogHeight, Pane pane) {
this.headingText = headingText;
this.bodyText = bodyText;
this.dialogBtnStyle = dialogBtnStyle;
this.dialogWidth = dialogWidth;
this.dialogHeight = dialogHeight;
this.pane = pane;
}
public void show() {
textArea = new JFXTextArea(bodyText);
JFXDialogLayout content = new JFXDialogLayout();
content.setHeading(new Text(headingText));
content.setBody(textArea);
content.setPrefSize(dialogWidth, dialogHeight);
StackPane stackPane = new StackPane();
stackPane.autosize();
JFXDialog dialog = new JFXDialog(stackPane, content, JFXDialog.DialogTransition.LEFT, true);
JFXButton button = new JFXButton("Okay");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
dialog.close();
}
});
button.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED);
button.setPrefHeight(32);
button.setStyle(dialogBtnStyle);
content.setActions(button);
pane.getChildren().add(stackPane);
AnchorPane.setTopAnchor(stackPane, (pane.getHeight() - content.getPrefHeight()) / 2);
AnchorPane.setLeftAnchor(stackPane, (pane.getWidth() - content.getPrefWidth()) / 2);
dialog.show();
}
public JFXTextArea getTextArea() {
return textArea;
}
public void setTextArea(JFXTextArea textArea) {
this.textArea = textArea;
}
}

View File

@ -1,7 +1,7 @@
/** /**
* cemu_UI * cemu_UI
* *
* Copyright 2017-2019 <@Seil0> * Copyright 2017 <@Seil0>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -21,16 +21,20 @@
package com.cemu_UI.vendorCloudController; package com.cemu_UI.vendorCloudController;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import com.cemu_UI.controller.XMLController;
import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
@ -52,11 +56,15 @@ import com.google.api.services.drive.model.FileList;
public class GoogleDriveController { public class GoogleDriveController {
Drive service; Drive service;
private String folderID = XMLController.getFolderID(); private String saveDirectory;
private File downloadFile; private String folderID;
private ArrayList<java.io.File> localSavegames = new ArrayList<>();
private ArrayList<File> cloudSavegames = new ArrayList<>();
private ArrayList<String> localSavegamesName = new ArrayList<>();
private ArrayList<String> cloudSavegamesName = new ArrayList<>();
private static final Logger LOGGER = LogManager.getLogger(GoogleDriveController.class.getName()); private static final Logger LOGGER = LogManager.getLogger(GoogleDriveController.class.getName());
private final String APPLICATION_NAME ="cemu_Ui Google Drive API Controller"; private final String APPLICATION_NAME ="cemu_Ui Drive API Controller"; //TODO add Google
//Directory to store user credentials for this application //Directory to store user credentials for this application
private final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".credentials/cemu_UI_credential"); private final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".credentials/cemu_UI_credential");
@ -79,7 +87,7 @@ public class GoogleDriveController {
try { try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR); DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
folderID = ""; // TODO why do we do this? folderID = "";
} catch (Throwable t) { } catch (Throwable t) {
LOGGER.error("error", t); LOGGER.error("error", t);
System.exit(1); System.exit(1);
@ -88,7 +96,6 @@ public class GoogleDriveController {
/** /**
* Creates an authorized Credential object. * Creates an authorized Credential object.
*
* @return an authorized Credential object. * @return an authorized Credential object.
* @throws IOException * @throws IOException
*/ */
@ -96,8 +103,10 @@ public class GoogleDriveController {
// Load client secrets. // Load client secrets.
InputStream in = getClass().getClassLoader().getResourceAsStream("client_secret.json"); InputStream in = getClass().getClassLoader().getResourceAsStream("client_secret.json");
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build(); .setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline")
.build();
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user"); Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
LOGGER.info("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath()); LOGGER.info("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
@ -106,24 +115,79 @@ public class GoogleDriveController {
/** /**
* Build and return an authorized Drive client service. * Build and return an authorized Drive client service.
*
* @return an authorized Drive client service * @return an authorized Drive client service
* @throws IOException * @throws IOException
*/ */
public Drive getDriveService() throws IOException { public Drive getDriveService() throws IOException {
Credential credential = authorize(); Credential credential = authorize();
return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build(); return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
} }
public void main(String cemuDirectory) throws IOException { public void main(String cemuDirectory) throws IOException {
java.io.File dir = new java.io.File(cemuDirectory + "/mlc01/usr/save");
service = getDriveService(); service = getDriveService();
// cemu >= 1.11 uses /mlc01/usr/save/... instead of /mlc01/emulatorSave/...
if (dir.exists()) {
LOGGER.info("using new save path");
saveDirectory = cemuDirectory + "/mlc01/usr/save";
} else {
LOGGER.info("using old save path");
saveDirectory = cemuDirectory + "/mlc01/emulatorSave";
}
}
public void sync(String cemuDirectory) throws IOException {
//in case there is no folderID saved, look it up first
if (getFolderID() == "" || getFolderID() == null) { if (getFolderID() == "" || getFolderID() == null) {
getSavegamesFolderID(); getSavegamesFolderID();
} }
getLocalSavegames();
getCloudSavegames();
// download files from cloud which don't exist locally
for (int i = 0; i < cloudSavegames.size(); i++) {
// if the file exists locally, check which one is newer
if (localSavegamesName.contains(cloudSavegames.get(i).getName())) {
int localSavegamesNumber = localSavegamesName.indexOf(cloudSavegames.get(i).getName());
long localModified = new DateTime(localSavegames.get(localSavegamesNumber).lastModified()).getValue();
long cloudModified = cloudSavegames.get(i).getModifiedTime().getValue();
FileInputStream fis = new FileInputStream(localSavegames.get(localSavegamesNumber));
if (cloudSavegames.get(i).getMd5Checksum().equals(org.apache.commons.codec.digest.DigestUtils.md5Hex(fis))) {
LOGGER.info("both files are the same, nothing to do");
} else {
if (localModified >= cloudModified) {
LOGGER.info("local is newer");
updateFile(cloudSavegames.get(i), localSavegames.get(localSavegamesNumber));
} else {
LOGGER.info("cloud is newer");
downloadFile(cloudSavegames.get(i));
}
} }
// create a folder in google drive } else {
LOGGER.info("file doesn't exist locally");
downloadFile(cloudSavegames.get(i));
}
}
// upload file to cloud which don't exist in the cloud
for (int j = 0; j < localSavegames.size(); j++) {
if (!cloudSavegamesName.contains(localSavegamesName.get(j))) {
LOGGER.info("file doesn't exist in the cloud");
uploadFile(localSavegames.get(j));
}
}
}
//create a folder in google drive
public void creatFolder() throws IOException { public void creatFolder() throws IOException {
LOGGER.info("creating new folder"); LOGGER.info("creating new folder");
File fileMetadata = new File(); File fileMetadata = new File();
@ -135,7 +199,7 @@ public class GoogleDriveController {
folderID = file.getId(); folderID = file.getId();
} }
// check if folder already exist //check if folder already exist
public boolean checkFolder() { public boolean checkFolder() {
try { try {
Files.List request = service.files().list().setQ("mimeType = 'application/vnd.google-apps.folder' and name = 'cemu_savegames'"); Files.List request = service.files().list().setQ("mimeType = 'application/vnd.google-apps.folder' and name = 'cemu_savegames'");
@ -151,58 +215,32 @@ public class GoogleDriveController {
} }
} }
// FIXME it seams like there is a bug in this method //reading all local savegames
// get the name of the zip in the semu_savegames folder, which is the last upload Unix time private void getLocalSavegames() throws IOException {
public long getLastCloudSync() throws IOException { java.io.File dir = new java.io.File(saveDirectory);
LOGGER.info("getting last cloud sync"); String[] extensions = new String[] { "dat","sav","bin" };
long lastCloudSync = 0; localSavegames.removeAll(localSavegames);
localSavegamesName.removeAll(localSavegamesName);
LOGGER.info("Getting all dat,sav,bin files in " + dir.getCanonicalPath()+" including those in subdirectories");
List<java.io.File> files = (List<java.io.File>) FileUtils.listFiles(dir, extensions, true);
for (java.io.File file : files) {
localSavegamesName.add(file.getParentFile().getName()+"_"+file.getName());
localSavegames.add(file);
}
}
//reading all cloud savegames
private void getCloudSavegames() throws IOException {
LOGGER.info("getting all cloud savegames");
cloudSavegames.removeAll(cloudSavegames);
cloudSavegamesName.removeAll(cloudSavegamesName);
Files.List request = service.files().list().setQ("'"+folderID+"' in parents").setFields("nextPageToken, files(id, name, size, modifiedTime, createdTime, md5Checksum)"); Files.List request = service.files().list().setQ("'"+folderID+"' in parents").setFields("nextPageToken, files(id, name, size, modifiedTime, createdTime, md5Checksum)");
FileList files = request.execute(); FileList files = request.execute();
for (File file : files.getFiles()) { for (File file : files.getFiles()) {
downloadFile = file; cloudSavegamesName.add(file.getName());
lastCloudSync = Long.parseLong(file.getName().substring(0, file.getName().length()-4)); cloudSavegames.add(file);
} }
return lastCloudSync;
}
/**
* delete all existing files in cemu_savegames at first
* upload the new savegames zip file
* @param uploadFile savegames zip file
* @throws IOException
*/
public void uploadZipFile(java.io.File uploadFile) throws IOException{
LOGGER.info("deleting old savegames ...");
Files.List request = service.files().list().setQ("'"+folderID+"' in parents").setFields("nextPageToken, files(id, name, size, modifiedTime, createdTime, md5Checksum)");
FileList files = request.execute();
for (File file : files.getFiles()) {
service.files().delete(file.getId()).execute(); // deleting old file
}
LOGGER.info("uploading " + uploadFile.getName() + " ...");
File fileMetadata = new File();
fileMetadata.setName(uploadFile.getName());
fileMetadata.setParents(Collections.singletonList(folderID));
fileMetadata.setModifiedTime(new DateTime(uploadFile.lastModified()));
FileContent mediaContent = new FileContent("", uploadFile);
File file = service.files().create(fileMetadata, mediaContent).setFields("id, parents").execute();
LOGGER.info("upload successfull, File ID: " + file.getId());
}
// download zip file from the cloud and unzip it
public java.io.File downloadZipFile(String cemu_UIDirectory) throws IOException{
LOGGER.info("downloading "+downloadFile.getName()+" ...");
java.io.File outputFile = new java.io.File(cemu_UIDirectory + "/" + downloadFile.getName());
OutputStream outputStream = new FileOutputStream(outputFile);
service.files().get(downloadFile.getId()).executeMediaAndDownloadTo(outputStream);
outputStream.close();
LOGGER.info("download successfull: " + downloadFile.getName());
return outputFile;
} }
private void getSavegamesFolderID() throws IOException { private void getSavegamesFolderID() throws IOException {
@ -211,14 +249,76 @@ public class GoogleDriveController {
try { try {
LOGGER.info("FolderID: " + files.getFiles().get(0).getId()); LOGGER.info("FolderID: " + files.getFiles().get(0).getId());
folderID = files.getFiles().get(0).getId(); setFolderID(files.getFiles().get(0).getId());
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("Oops, something went wrong! It seems that you have more than one folder called 'cemu_savegames'!", e); LOGGER.error("Oops, something went wrong! It seems that you have more than one folder called 'cemu_savegames'!", e);
} }
} }
//upload a file to the cloud from the local savegames folder
public void uploadFile(java.io.File uploadFile) throws IOException{
LOGGER.info("uploading " + uploadFile.getName() + " ...");
File fileMetadata = new File();
fileMetadata.setName(uploadFile.getParentFile().getName()+"_"+uploadFile.getName());
fileMetadata.setParents(Collections.singletonList(folderID));
fileMetadata.setModifiedTime(new DateTime(uploadFile.lastModified()));
FileContent mediaContent = new FileContent("", uploadFile);
File file = service.files().create(fileMetadata, mediaContent).setFields("id, parents").execute();
LOGGER.info("upload successfull, File ID: " + file.getId());
}
//download a file from the cloud to the local savegames folder
private void downloadFile(File downloadFile) throws IOException{
LOGGER.info("downloading "+downloadFile.getName()+" ...");
java.io.File directory = new java.io.File(saveDirectory + "/" + downloadFile.getName().substring(0,8));
String file = downloadFile.getName().substring(9,downloadFile.getName().length());
if(!directory.exists()) {
LOGGER.info("dir dosent exist");
directory.mkdir();
}
OutputStream outputStream = new FileOutputStream(directory +"/"+ file);
service.files().get(downloadFile.getId()).executeMediaAndDownloadTo(outputStream);
outputStream.close();
LOGGER.info("download successfull, File ID: " + file); //TODO add FileID
}
//update a file in the cloud, by deleting the old one and uploading an new with the same id
private void updateFile(File oldFile, java.io.File newFile) throws IOException {
LOGGER.info("updating " +oldFile.getName()+" ...");
service.files().delete(oldFile.getId()).execute(); //deleting old file
//uploading new file
File fileMetadata = new File();
fileMetadata.setName(newFile.getParentFile().getName()+"_"+newFile.getName());
fileMetadata.setParents(Collections.singletonList(folderID));
fileMetadata.setModifiedTime(new DateTime(newFile.lastModified()));
FileContent mediaContent = new FileContent("", newFile);
File file = service.files().create(fileMetadata, mediaContent).setFields("id, parents").execute();
LOGGER.info("update successfull, File ID: " + file.getId());
}
public void uploadAllFiles() {
try {
getLocalSavegames();
LOGGER.info("uploading " + localSavegames.size() + " files ...");
for (int i = 0; i < localSavegames.size(); i++) {
uploadFile(localSavegames.get(i));
}
LOGGER.info("finished uploading all files");
} catch (IOException e) {
LOGGER.error("error while uploading all files", e);
}
}
public String getFolderID() { public String getFolderID() {
return folderID; return folderID;
} }
public void setFolderID(String folderID) {
this.folderID = folderID;
}
} }

View File

@ -1,8 +1,6 @@
/******************************************************************************* /*
* * * HAMBURGER CSS
* Hamburger Menu * */
* *
******************************************************************************/
.jfx-hamburgerW StackPane { .jfx-hamburgerW StackPane {
-fx-background-color: white; -fx-background-color: white;
@ -14,11 +12,9 @@
-fx-background-radius: 5px; -fx-background-radius: 5px;
} }
/******************************************************************************* /*
* * * TREE TABLE CSS
* TreeTable * */
* *
******************************************************************************/
.tree-table-view { .tree-table-view {
-fx-tree-table-color: rgba(0, 168, 204, 0.2); -fx-tree-table-color: rgba(0, 168, 204, 0.2);
@ -85,138 +81,6 @@
-fx-background-color: -fx-tree-table-color, -fx-box-border, -fx-control-inner-background; -fx-background-color: -fx-tree-table-color, -fx-box-border, -fx-control-inner-background;
-fx-background-insets: -1.4, 0, 1; -fx-background-insets: -1.4, 0, 1;
-fx-background-radius: 1.4, 0, 0; -fx-background-radius: 1.4, 0, 0;
/*....*/
-fx-padding: 1; /* 0.083333em; */ -fx-padding: 1; /* 0.083333em; */
} }
/*******************************************************************************
* *
* ChoiceBox *
* *
******************************************************************************/
.choice-box {
-fx-background-color: transparent;
-fx-border-color: #000000;
-fx-border-width: 0 0 1 0;
-fx-background-radius: 0;
-fx-border-radius: 0;
}
.choice-box:focused {
-fx-border-color: #9E9E9E;
}
.choice-box>.open-button>.arrow {
-fx-background-color: #757575;
}
.menu-item:focused {
-fx-background-color: #00A8CC;
}
/*******************************************************************************
* *
* Spinner *
* *
******************************************************************************/
.spinner {
-fx-background-color: #f4f4f4;
}
/*******************************************************************************
* *
* ScrollBar *
* *
******************************************************************************/
.scroll-bar:vertical, .scroll-bar:horizontal {
-fx-background-color: transparent;
}
.scroll-bar:vertical > .track-background, .scroll-bar:horizontal > .track-background {
-fx-background-color: transparent;
-fx-background-insets: 0.0;
}
.scroll-bar:vertical > .thumb {
-fx-background-color: #BCBCBC;
-fx-background-insets: 0.0;
-fx-background-radius: 15.0;
}
.scroll-bar:horizontal > .thumb {
-fx-background-color: #FFFFFF;
-fx-background-insets: 0.0;
-fx-background-radius: 15.0;
}
/* Up- and Down-Button Padding */
.scroll-bar:vertical > .increment-button, .scroll-bar:vertical > .decrement-button {
-fx-padding: 5 2 5 2;
}
/* Left- and Right-Button Padding */
.scroll-bar:horizontal > .increment-button, .scroll-bar:horizontal > .decrement-button {
-fx-background-color: transparent;
-fx-padding: 5 2 5 2;
}
.scroll-bar > .increment-button, .scroll-bar > .decrement-button, .scroll-bar:hover > .increment-button, .scroll-bar:hover > .decrement-button {
-fx-background-color: transparent;
}
.scroll-bar > .increment-button > .increment-arrow, .scroll-bar > .decrement-button > .decrement-arrow {
-fx-background-color: rgb(150.0, 150.0, 150.0);
}
/* Up Arrow */
.scroll-bar:vertical > .increment-button > .increment-arrow {
-fx-shape: "M298 426h428l-214 214z";
}
/* Down Arrow */
.scroll-bar:vertical > .decrement-button > .decrement-arrow {
-fx-shape: "M298 598l214-214 214 214h-428z";
}
/* Right Arrow */
.scroll-bar:horizontal > .increment-button > .increment-arrow {
/* -fx-shape: "M0 428l0 -428l214 214l-214 214z"; */
-fx-background-color:transparent;
-fx-shape: " ";
-fx-padding: 0;
}
/* Left Arrow */
.scroll-bar:horizontal > .decrement-button > .decrement-arrow {
/* -fx-shape: "M214 0l0 428l-214 -214l214 -214z"; */
-fx-background-color:transparent;
-fx-shape: " ";
-fx-padding: 0;
}
/*******************************************************************************
* *
* ScrollPane *
* *
******************************************************************************/
.scroll-pane {
-fx-background-insets: 0;
-fx-padding: 0;
}
.scroll-pane:focused {
-fx-background-insets: 0;
}
.scroll-pane .corner {
-fx-background-insets: 0;
}
.scroll-pane > .viewport {
-fx-background-color: transparent;
}

View File

@ -13,24 +13,56 @@
<?import javafx.scene.control.Separator?> <?import javafx.scene.control.Separator?>
<?import javafx.scene.image.ImageView?> <?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<?import javafx.scene.text.TextFlow?> <?import javafx.scene.text.TextFlow?>
<AnchorPane fx:id="mainAnchorPane" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="1130.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"> <AnchorPane fx:id="mainAnchorPane" prefHeight="600.0" prefWidth="904.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.cemu_UI.application.MainWindowController">
<children> <children>
<ScrollPane fx:id="mainScrollPane" fitToWidth="true" layoutY="38.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="38.0"> <ScrollPane fx:id="mainScrollPane" fitToWidth="true" layoutY="38.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="38.0">
<content> <content>
<FlowPane fx:id="gamesFlowPane" hgap="3.0" vgap="7.0"> <AnchorPane fx:id="gamesAnchorPane">
<padding> <padding>
<Insets bottom="17.0" /> <Insets bottom="17.0" />
</padding> </padding></AnchorPane>
</FlowPane>
</content> </content>
</ScrollPane> </ScrollPane>
<ScrollPane fx:id="settingsScrollPane" fitToHeight="true" fitToWidth="true" prefHeight="562.0" prefWidth="729.0" style="-fx-background: white;" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="175.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="38.0"> <HBox fx:id="topHBox" prefHeight="38.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<JFXHamburger fx:id="menuHam" prefHeight="38.0" prefWidth="38.0" stylesheets="@../css/MainWindows.css" />
</children>
</HBox>
<VBox fx:id="sideMenuVBox" layoutY="32.0" prefHeight="568.0" prefWidth="175.0" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="38.0">
<children>
<JFXButton fx:id="aboutBtn" alignment="TOP_LEFT" maxHeight="38.0" maxWidth="190.0" onAction="#aboutBtnAction" prefHeight="38.0" prefWidth="190.0" text="About" textAlignment="LEFT">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
<JFXButton fx:id="settingsBtn" alignment="TOP_LEFT" maxHeight="38.0" maxWidth="213.0" onAction="#settingsBtnAction" prefHeight="38.0" prefWidth="213.0" text="Settings" textAlignment="LEFT">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
<JFXButton fx:id="addBtn" alignment="TOP_LEFT" maxHeight="38.0" maxWidth="193.0" onAction="#addBtnAction" prefHeight="38.0" prefWidth="193.0" text="Add new Game" textAlignment="LEFT">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
<JFXButton fx:id="reloadRomsBtn" alignment="TOP_LEFT" maxHeight="38.0" maxWidth="199.0" onAction="#reloadRomsBtnAction" prefHeight="38.0" prefWidth="199.0" text="reload roms" textAlignment="LEFT">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
<JFXButton fx:id="smmdbBtn" alignment="TOP_LEFT" onAction="#smmdbBtnAction" prefHeight="38.0" prefWidth="216.0" text="smmdb">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
</children>
</VBox>
<ScrollPane fx:id="settingsScrollPane" prefHeight="562.0" prefWidth="729.0" style="-fx-background: white;" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="175.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="38.0">
<content> <content>
<!-- space between settings sections 35px, between sections elements (label + element) 20px, between label and element 3px(or more) --> <!-- space between settings sections 35px, between sections elements (label + element) 20px, between label and element 3px(or more) -->
<AnchorPane fx:id="settingsAnchorPane" prefHeight="686.0" prefWidth="711.0" style="-fx-background-color: white;"> <AnchorPane fx:id="settingsAnchorPane" prefHeight="686.0" prefWidth="711.0" style="-fx-background-color: white;">
@ -39,7 +71,7 @@
<children> <children>
<VBox prefHeight="485.0" prefWidth="710.0" spacing="25.0"> <VBox prefHeight="485.0" prefWidth="710.0" spacing="25.0">
<children> <children>
<VBox> <VBox prefHeight="21.0" prefWidth="676.0">
<children> <children>
<Label fx:id="cemu_UISettingsLbl" text="cemu_UI Settings"> <Label fx:id="cemu_UISettingsLbl" text="cemu_UI Settings">
<font> <font>
@ -59,12 +91,12 @@
<Insets left="-14.0" /> <Insets left="-14.0" />
</padding> </padding>
</VBox> </VBox>
<VBox spacing="7.0"> <VBox spacing="10.0">
<children> <children>
<Label fx:id="cemuDirectoryLbl" text="Cemu Directory" /> <Label fx:id="cemuDirectoryLbl" text="Cemu Directory" />
<HBox spacing="10.0"> <HBox spacing="10.0">
<children> <children>
<JFXTextField fx:id="cemuTextField" maxWidth="305.0" minWidth="305.0" prefHeight="32.0" prefWidth="305.0" promptText="cemu directory" /> <JFXTextField fx:id="cemuTextField" maxWidth="305.0" minWidth="305.0" onAction="#cemuTextFieldAction" prefHeight="32.0" prefWidth="305.0" promptText="cemu directory" />
<JFXButton fx:id="cemuTFBtn" onAction="#cemuTFBtnAction" prefHeight="32.0" text="choose directory" /> <JFXButton fx:id="cemuTFBtn" onAction="#cemuTFBtnAction" prefHeight="32.0" text="choose directory" />
</children> </children>
</HBox> </HBox>
@ -73,12 +105,12 @@
<Insets right="5.0" /> <Insets right="5.0" />
</padding> </padding>
</VBox> </VBox>
<VBox spacing="7.0"> <VBox spacing="10.0">
<children> <children>
<Label fx:id="romDirectoryLbl" text="Rom Directory" /> <Label fx:id="romDirectoryLbl" text="Rom Directory" />
<HBox spacing="10.0"> <HBox spacing="10.0">
<children> <children>
<JFXTextField fx:id="romTextField" maxWidth="305.0" minWidth="305.0" prefHeight="32.0" prefWidth="305.0" promptText="rom directory" /> <JFXTextField fx:id="romTextField" maxWidth="305.0" minWidth="305.0" onAction="#romTextFieldAction" prefHeight="32.0" prefWidth="305.0" promptText="rom directory" />
<JFXButton fx:id="romTFBtn" onAction="#romTFBtnAction" prefHeight="32.0" text="choose directory" /> <JFXButton fx:id="romTFBtn" onAction="#romTFBtnAction" prefHeight="32.0" text="choose directory" />
</children> </children>
</HBox> </HBox>
@ -86,16 +118,10 @@
</VBox> </VBox>
<HBox spacing="10.0"> <HBox spacing="10.0">
<children> <children>
<Label fx:id="mainColorLbl" minHeight="25.0" text="main Color" /> <Label fx:id="mainColorLbl" prefHeight="25.0" text="main Color" />
<JFXColorPicker fx:id="colorPicker" onAction="#colorPickerAction" /> <JFXColorPicker fx:id="colorPicker" onAction="#colorPickerAction" />
</children> </children>
</HBox> </HBox>
<HBox prefHeight="100.0" prefWidth="200.0" spacing="10.0">
<children>
<Label fx:id="languageLbl" prefHeight="25.0" text="language" />
<ChoiceBox fx:id="languageChoisBox" prefWidth="150.0" />
</children>
</HBox>
<JFXToggleButton fx:id="cloudSyncToggleBtn" onAction="#cloudSyncToggleBtnAction" text="cloud savegames (Google Drive)" /> <JFXToggleButton fx:id="cloudSyncToggleBtn" onAction="#cloudSyncToggleBtnAction" text="cloud savegames (Google Drive)" />
<VBox spacing="10.0"> <VBox spacing="10.0">
<children> <children>
@ -179,51 +205,13 @@
</ScrollPane> </ScrollPane>
</children> </children>
</AnchorPane> </AnchorPane>
<HBox fx:id="bottomHBox" alignment="CENTER" layoutX="326.0" layoutY="602.0" prefHeight="48.0" prefWidth="200.0" spacing="10.0" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"> <JFXButton fx:id="playBtn" buttonType="RAISED" layoutX="396.0" maxHeight="28.0" minWidth="100.0" onAction="#playBtnAction" ripplerFill="#00aacc" text="play" textAlignment="CENTER" visible="false" AnchorPane.bottomAnchor="12.0">
<children>
<JFXButton fx:id="totalPlaytimeBtn" buttonType="RAISED" maxHeight="32.0" maxWidth="156.0" minHeight="32.0" minWidth="156.0" onAction="#totalPlaytimeBtnAction" style="-fx-background-color: #ffffff; -fx-button-type: RAISED; -fx-text-fill: BLACK;" text="0 h 0 min">
</JFXButton>
<JFXButton fx:id="playBtn" buttonType="RAISED" maxHeight="28.0" minWidth="100.0" onAction="#playBtnAction" ripplerFill="#00aacc" text="play" textAlignment="CENTER">
<font> <font>
<Font name="System Bold" size="14.0" /> <Font name="System Bold" size="14.0" />
</font> </font>
</JFXButton> </JFXButton>
<JFXButton fx:id="lastTimePlayedBtn" buttonType="RAISED" maxHeight="32.0" maxWidth="156.0" minHeight="32.0" minWidth="156.0" onAction="#lastTimePlayedBtnAction" style="-fx-background-color: #ffffff; -fx-button-type: RAISED; -fx-text-fill: BLACK;" text="Last played, never" /> <JFXButton fx:id="totalPlaytimeBtn" buttonType="RAISED" layoutX="275.5" maxHeight="32.0" minWidth="100.0" onAction="#totalPlaytimeBtnAction" prefHeight="32.0" style="-fx-background-color: #ffffff; -fx-button-type: RAISED; -fx-text-fill: BLACK;" text="0 h 0 min" visible="false" AnchorPane.bottomAnchor="10.0">
</children>
</HBox>
<HBox fx:id="topHBox" prefHeight="38.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<JFXHamburger fx:id="menuHam" prefHeight="38.0" prefWidth="38.0" stylesheets="@../css/MainWindows.css" />
</children>
</HBox>
<VBox fx:id="sideMenuVBox" layoutY="32.0" prefHeight="568.0" prefWidth="175.0" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="38.0">
<children>
<JFXButton fx:id="aboutBtn" alignment="TOP_LEFT" maxHeight="38.0" maxWidth="190.0" onAction="#aboutBtnAction" prefHeight="38.0" prefWidth="190.0" text="About" textAlignment="LEFT">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton> </JFXButton>
<JFXButton fx:id="settingsBtn" alignment="TOP_LEFT" maxHeight="38.0" maxWidth="213.0" onAction="#settingsBtnAction" prefHeight="38.0" prefWidth="213.0" text="Settings" textAlignment="LEFT"> <JFXButton fx:id="lastTimePlayedBtn" buttonType="RAISED" layoutX="516.5" maxHeight="32.0" minWidth="100.0" onAction="#lastTimePlayedBtnAction" prefHeight="32.0" style="-fx-background-color: #ffffff; -fx-button-type: RAISED; -fx-text-fill: BLACK;" text="Last played, never" visible="false" AnchorPane.bottomAnchor="10.0" />
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
<JFXButton fx:id="addBtn" alignment="TOP_LEFT" maxHeight="38.0" maxWidth="193.0" onAction="#addBtnAction" prefHeight="38.0" prefWidth="193.0" text="Add new Game" textAlignment="LEFT">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
<JFXButton fx:id="reloadRomsBtn" alignment="TOP_LEFT" maxHeight="38.0" maxWidth="199.0" onAction="#reloadRomsBtnAction" prefHeight="38.0" prefWidth="199.0" text="reload roms" textAlignment="LEFT">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
<JFXButton fx:id="smmdbBtn" alignment="TOP_LEFT" onAction="#smmdbBtnAction" prefHeight="38.0" prefWidth="216.0" text="smmdb">
<font>
<Font name="System Bold" size="14.0" />
</font>
</JFXButton>
</children>
</VBox>
</children> </children>
</AnchorPane> </AnchorPane>

View File

@ -1,87 +0,0 @@
#HomeFlix-Local_de_DE.properties DE-Deutsch Local
# Buttons
aboutBtn = \u00dcber
settingsBtn = Einstellungen
addBtn = Spiel hinzuf\u00fcgen
reloadRomsBtn = ROMs neu laden
smmdbBtn = smmdb
cemuTFBtn = Ordner \u00F6ffnen
romTFBtn = Ordner \u00F6ffnen
smmdbDownloadBtn = Download
playBtn = spielen
cloudSyncToggleBtn = Spielst\u00e4nde \u00fcber die Cloud syncronisieren (Google Drive)
autoUpdateToggleBtn = beim Start nach Updates suchen
fullscreenToggleBtn = Spiel im Vollbildmodus starten
# Labels
cemu_UISettingsLbl = cemu_UI Einstellungen
cemuDirectoryLbl = cemu directory
romDirectoryLbl = ROM directory
mainColorLbl = Hauptfarbe
languageLbl = Sprache
updateLbl = updates
branchLbl = Updatezweig
cemuSettingsLbl = cemu Einstellungen
licensesLbl = Lizenzen
# Columns
titleColumn = Titel
idColumn = ID
starsColumn = Sterne
timeColumn = Zeit
# Strings
editHeadingText = bearbeiten
editBodyText = Du kannst den Title und den ROM-/Coverpfad bearbeiten.
removeHeadingText = löschen
removeBodyText = Bist du sicher dass du flgendes Spiel l\u00f6schen m\u00f6chtest
addUpdateHeadingText = update
addUpdateBodyText = Bitte w\u00e4hle das Update-Verzeichniss aus.
addDLCHeadingText = ein DLC hinzufügen
addDLCBodyText = Bitte w\u00e4hle das DLC-Verzeichniss aus.
licensesLblHeadingText = cemu_UI
licensesLblBodyText = cemu_UI ist lizensiert unter der GNU GPL 3.\n\nJFoenix, Apache License 2.0\nminimal-json, MIT License\nsqlite-jdbc, Apache License 2.0\nApache Commons IO, Apache License 2.0\nApache Commons Logging, Apache License 2.0\nApache Commons Codec, Apache License 2.0\nApache Log4j 2, Apache License 2.0\n
showLicenses = Lizenzen \u00f6ffnen
aboutBtnHeadingText = cemu_UI
aboutBtnBodyText = Diese Programm wurde mit freier Software erstellt\nund ist lizensiert unter der GNU GPL 3.\n\nwww.mosad.xyz
cloudSyncWaringHeadingText = Spielst\u00e4nde über die Cloud syncronisieren (beta)
cloudSyncWaringBodyText = WARNING this is a completly WIP cloud save integration,\nit's NOT recomended to use this!!\n\nUse it on your own risk and backup everthing before!
cloudSyncErrorHeadingText = Fehler beim initialisieren der Cloud-Verbindung!
cloudSyncErrorBodyText = Fehler beim initialisieren der Cloud-Verbindung.\nBitte lade die app.log (welceh du im cemu_UI Verzeichniss findest)\nauf \"https://github.com/Seil0/cemu_UI/issues\" hoch.
addGameBtnHeadingText = eine neues Spiel zu cemu_Ui hinzuf\u00fcgen
addGameBtnBodyText =
addBtnReturnErrorHeadingText = Fehler beim hinzuf\u00fcgen des Spiels!
addBtnReturnErrorBodyText = Fehler beim hinzuf\u00fcgen des Spiels.\nEiner der benötigten Werte war leer, bitte versuche es erneut.
lastPlayed = zuletzt gespielt,
today = heute
yesterday = gestern
never = nie
# button strings
playBtnPlay = spieles
playBtnUpdating = updating...
playBtnCopyingFiles = kopiere Dateien...
smmdbDownloadBtnLoading = laden
smmdbDownloadBtnDownload = Download
okayBtnText = okay
cancelBtnText = abbruch
updateBtnCheckNow = Auf Update pr\u00FCfen
updateBtnChecking = Es wird nach Updates gesucht...
updateBtnNoUpdateAvailable = Kein Update verf\u00FCgbar
updateBtnUpdateAvailable = Update verf\u00FCgbar
#EditGameDialog
gameTitle = Spiel Titel
titleID = Titel ID
romPath = ROM Pfad
coverPath = Cover-Pfad
editGameDialogHeadingTextError = Fehler beim hinzuf\u00fcgen des Spiels!
editGameDialogBodyTextError = Fehler beim hinzuf\u00fcgen des Spiels.\nEiner der benötigten Werte war leer, bitte versuche es erneut.
editGameDialogSelectPathBtn = .rpx Datei ausw\u00E4hlen
editGameDialogSelectCoverBtn = cover Datei ausw\u00E4hlen

View File

@ -1,87 +0,0 @@
#HomeFlix-Local_en_US.properties US-English Local and default
# Buttons
aboutBtn = About
settingsBtn = Settings
addBtn = Add new Game
reloadRomsBtn = reload ROMs
smmdbBtn = smmdb
cemuTFBtn = choose directory
romTFBtn = choose directory
smmdbDownloadBtn = Download
playBtn = play
cloudSyncToggleBtn = cloud savegames (Google Drive)
autoUpdateToggleBtn = check for updates on startup
fullscreenToggleBtn = start game in fullscreen
# Labels
cemu_UISettingsLbl = cemu_UI Settings
cemuDirectoryLbl = cemu directory
romDirectoryLbl = ROM directory
mainColorLbl = primary color
languageLbl = Language
updateLbl = Updates
branchLbl = Branch
cemuSettingsLbl = cemu Settings
licensesLbl = Licenses
# Columns
titleColumn = title
idColumn = ID
starsColumn = stars
timeColumn = time
# Strings
editHeadingText = edit
editBodyText = You can edit the tile and ROM/cover path.
removeHeadingText = remove
removeBodyText = Are you sure you want to delete
addUpdateHeadingText = update
addUpdateBodyText = Please select the update root directory.
addDLCHeadingText = add a DLC to
addDLCBodyText = Please select the DLC root directory.
licensesLblHeadingText = cemu_UI
licensesLblBodyText = cemu_UI is licensed under the terms of GNU GPL 3.\n\nJFoenix, Apache License 2.0\nminimal-json, MIT License\nsqlite-jdbc, Apache License 2.0\nApache Commons IO, Apache License 2.0\nApache Commons Logging, Apache License 2.0\nApache Commons Codec, Apache License 2.0\nApache Log4j 2, Apache License 2.0\n
showLicenses = show licenses
aboutBtnHeadingText = cemu_UI
aboutBtnBodyText = This Application is made with free Software\nand licensed under the terms of GNU GPL 3.\n\nwww.mosad.xyz
cloudSyncWaringHeadingText = activate cloud savegame sync (beta)
cloudSyncWaringBodyText = WARNING this is a completely WIP cloud save integration,\nit's NOT recommended to use this!!\n\nUse it on your own risk and backup everything before!
cloudSyncErrorHeadingText = Error while initializing cloud sync!
cloudSyncErrorBodyText = There was some trouble while initializing cloud sync.\nPlease upload the app.log (which can be found in the cemu_UI directory)\nto \"https://github.com/Seil0/cemu_UI/issues\" so we can fix this.
addGameBtnHeadingText = add a new game to cemu_UI
addGameBtnBodyText =
addBtnReturnErrorHeadingText = Error while adding a new Game!
addBtnReturnErrorBodyText = There was some trouble adding your game.\nOne of the needed values was empty, please try again to add your game.
lastPlayed = Last played,
today = today
yesterday = yesterday
never = never
# button strings
playBtnPlay = play
playBtnUpdating = updating...
playBtnCopyingFiles = copying files...
smmdbDownloadBtnLoading = loading
smmdbDownloadBtnDownload = Download
okayBtnText = okay
cancelBtnText = cancel
updateBtnCheckNow = check now!
updateBtnChecking = checking for updates ...
updateBtnNoUpdateAvailable = no update available
updateBtnUpdateAvailable = update available
#EditGameDialog
gameTitle = game title
titleID = title ID
romPath = ROM path
coverPath = cover path
editGameDialogHeadingTextError = Error while adding a new Game!
editGameDialogBodyTextError = There was some trouble adding your game.\nOne of the needed values was empty, please try again to add your game.
editGameDialogSelectPathBtn = select .rpx file
editGameDialogSelectCoverBtn = select cover file

View File

@ -1,5 +1,8 @@
package com.cemu_UI.test; package com.cemu_UI.test;
import java.io.File;
import junit.framework.Assert;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestCase; import junit.framework.TestCase;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@ -21,7 +24,8 @@ public class AppTest extends TestCase {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private void testClientsSecret() { private void testClientsSecret() {
File client_secret = new File("/client_secret.json");
Assert.assertTrue(client_secret.exists());
} }
/** /**