diff --git a/.classpath b/.classpath index bf77390..e83910a 100644 --- a/.classpath +++ b/.classpath @@ -1,11 +1,27 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.directory b/.directory deleted file mode 100644 index 4209d5a..0000000 --- a/.directory +++ /dev/null @@ -1,3 +0,0 @@ -[Dolphin] -Timestamp=2016,8,15,12,18,4 -Version=3 diff --git a/.gitignore b/.gitignore index 0cf5b30..f8db64b 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,6 @@ Temporary Items .apdisk config.xml .directory +target/ +apiKeys.json diff --git a/.project b/.project index b4e5ab5..01f0bec 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - Project HomeFlix + Project-HomeFlix @@ -11,14 +11,13 @@ - org.eclipse.xtext.ui.shared.xtextBuilder + org.eclipse.m2e.core.maven2Builder - org.eclipse.xtext.ui.shared.xtextNature org.eclipse.jdt.core.javanature - org.eclipse.fx.ide.css.nature + org.eclipse.m2e.core.maven2Nature diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..839d647 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -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/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index a698e59..4a6c6b8 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,5 @@ 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.source=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=9 +org.eclipse.jdt.core.compiler.compliance=9 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=9 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..5b38789 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at admin@kellerkinder.xyz. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/README.md b/README.md index c12c841..7a798c0 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,24 @@ +![Total Downloads](https://img.shields.io/github/downloads/Seil0/Project-HomeFlix/total.svg?style=flat-square) +[![Latest](https://img.shields.io/github/release/Seil0/Project-HomeFlix/all.svg?style=flat-square)](https://github.com/Seil0/Project-HomeFlix/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) + # Project-HomeFlix +Project-HomeFlix is a Kellerkinder Project, that alowes you to sort all your local saved movies in clean UI. Project-HomeFlix is free and open-source software and uses other open-source projects to provied a nice user experience. +## Installation +Simply download the Project-HomeFlix.jar from [releases](https://github.com/Seil0/Project-HomeFlix/releases), make sure you have the latest version of java 8 oracle jre/jdk installed, open the .jar file. If you need additional information pleas visit our [wiki](https://github.com/Seil0/Project-HomeFlix/wiki). -Project HomeFlix is a Kellerkinder Project, that alowes you to sort all your local saved movies in clean UI. +## Development information The dev branch is **only merged** into master when a **new release** is released, so **master contains the latest released version**. Please commit all changes to [dev](https://github.com/Seil0/Project-HomeFlix/tree/dev). -**Due to some changes with the API we use(not provided by us), the query does not work at the moment!** - Librarys used in this Project: JFoenix: https://github.com/jfoenixadmin/JFoenix minimal-json: https://github.com/ralfstx/minimal-json sqlite-jdbc: https://github.com/xerial/sqlite-jdbc apache commons io : https://commons.apache.org/proper/commons-io/ -## Installation +## screenshots +![Screenshot](https://github.com/Seil0/Seil0.github.io/blob/master/pictures/Project-HomeFlix_MainWindow.png) -[wiki](https://github.com/Seil0/Project-HomeFlix/wiki) - -Project HomeFlix © 2016-2017 Kellerkinder ([Seil0](https://github.com/Seil0), [Windoofs](https://github.com/Windoofs)) +Project-HomeFlix © 2016-2018 Kellerkinder ([Seil0](https://github.com/Seil0), [Windoofs](https://github.com/Windoofs)) www.kellerkinder.xyz diff --git a/bin/.gitignore b/bin/.gitignore deleted file mode 100644 index b42b859..0000000 --- a/bin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/application/ diff --git a/bin/application/DBController.class b/bin/application/DBController.class deleted file mode 100644 index fe33f4a..0000000 Binary files a/bin/application/DBController.class and /dev/null differ diff --git a/bin/application/Main.class b/bin/application/Main.class deleted file mode 100644 index 7ea09ff..0000000 Binary files a/bin/application/Main.class and /dev/null differ diff --git a/bin/application/MainWindow.fxml b/bin/application/MainWindow.fxml deleted file mode 100644 index 032c390..0000000 --- a/bin/application/MainWindow.fxml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/application/MainWindowController$1.class b/bin/application/MainWindowController$1.class deleted file mode 100644 index 83f39ab..0000000 Binary files a/bin/application/MainWindowController$1.class and /dev/null differ diff --git a/bin/application/MainWindowController$2.class b/bin/application/MainWindowController$2.class deleted file mode 100644 index 0598930..0000000 Binary files a/bin/application/MainWindowController$2.class and /dev/null differ diff --git a/bin/application/MainWindowController$3.class b/bin/application/MainWindowController$3.class deleted file mode 100644 index d3984f0..0000000 Binary files a/bin/application/MainWindowController$3.class and /dev/null differ diff --git a/bin/application/MainWindowController$4.class b/bin/application/MainWindowController$4.class deleted file mode 100644 index 805fc84..0000000 Binary files a/bin/application/MainWindowController$4.class and /dev/null differ diff --git a/bin/application/MainWindowController$5.class b/bin/application/MainWindowController$5.class deleted file mode 100644 index cdf339c..0000000 Binary files a/bin/application/MainWindowController$5.class and /dev/null differ diff --git a/bin/application/MainWindowController$6.class b/bin/application/MainWindowController$6.class deleted file mode 100644 index e7f5c3d..0000000 Binary files a/bin/application/MainWindowController$6.class and /dev/null differ diff --git a/bin/application/MainWindowController$7.class b/bin/application/MainWindowController$7.class deleted file mode 100644 index 0fed876..0000000 Binary files a/bin/application/MainWindowController$7.class and /dev/null differ diff --git a/bin/application/MainWindowController.class b/bin/application/MainWindowController.class deleted file mode 100644 index 9aca2d1..0000000 Binary files a/bin/application/MainWindowController.class and /dev/null differ diff --git a/bin/application/apiQuery.class b/bin/application/apiQuery.class deleted file mode 100644 index 83ad53e..0000000 Binary files a/bin/application/apiQuery.class and /dev/null differ diff --git a/bin/application/tableData.class b/bin/application/tableData.class deleted file mode 100644 index 76223fc..0000000 Binary files a/bin/application/tableData.class and /dev/null differ diff --git a/bin/application/updater.class b/bin/application/updater.class deleted file mode 100644 index 53dccc4..0000000 Binary files a/bin/application/updater.class and /dev/null differ diff --git a/bin/libraries/commons-io-2.5.jar b/bin/libraries/commons-io-2.5.jar deleted file mode 100644 index 107b061..0000000 Binary files a/bin/libraries/commons-io-2.5.jar and /dev/null differ diff --git a/bin/libraries/jfoenix-1.4.0.jar b/bin/libraries/jfoenix-1.4.0.jar deleted file mode 100644 index 789ef3b..0000000 Binary files a/bin/libraries/jfoenix-1.4.0.jar and /dev/null differ diff --git a/bin/libraries/minimal-json-0.9.4.jar b/bin/libraries/minimal-json-0.9.4.jar deleted file mode 100644 index 14c0633..0000000 Binary files a/bin/libraries/minimal-json-0.9.4.jar and /dev/null differ diff --git a/bin/libraries/sqlite-jdbc-3.18.0.jar b/bin/libraries/sqlite-jdbc-3.18.0.jar deleted file mode 100644 index 8e9dce1..0000000 Binary files a/bin/libraries/sqlite-jdbc-3.18.0.jar and /dev/null differ diff --git a/bin/resources/HomeFlix-Local_de_DE.properties b/bin/resources/HomeFlix-Local_de_DE.properties deleted file mode 100644 index aa9c214..0000000 --- a/bin/resources/HomeFlix-Local_de_DE.properties +++ /dev/null @@ -1,63 +0,0 @@ -#HomeFlix-Local_de_DE.properties German Local - -#main window translations -info = Info -settings = Einstellungen -streamingSettings = Stream Einst. -tfSearch = Suche... -openFolder = Ordner \u00F6ffnen - -#settings translations -settingsHead1Label = HomeFlix Einstellungen -tfPath = Pfad... -chooseFolder = Ordner ausw\u00E4hlen -mainColorLabel = Hauptfarbe: -fontsizeLabel = Schriftgr\u00F6\u00DFe: -localLabel = Sprache: -checkUpdates = Auf Update pr\u00FCfen -checkingUpdates = Es wird nach Updates gesucht... -updateBtnavail = Update verf\u00FCgbar -updateBtnNotavail = Kein Update verf\u00FCgbar -autoUpdateLabel = beim Start nach Updates suchen: -version = Version: - -#column translations -columnName = Name -columnRating = Bewertung -columnStreamUrl = Datei Name -columnResolution = Aufl\u00F6sung -columnSeason = Staffel -columnYear = Jahr - -#error translations -errorUpdateV = Beim ausf\u00FChren des Updates ist ein Fehler aufgetreten! \nError: could not check update version (nvc)\nWeitere Hilfe erhalten sie unter www.kellerkinder.xyz \noder wenden sie sich an support@kellerkinder.xyz -errorUpdateD = Beim ausf\u00FChren des Updates ist ein Fehler aufgetreten! \nError: could not download update files (ndf)\nWeitere Hilfe erhalten sie unter www.kellerkinder.xyz \noder wenden sie sich an support@kellerkinder.xyz -errorPlay = Beim \u00F6ffnen der Datei ist ein Fehler aufgetreten! \nError: could not open file (nof) \nWeitere Hilfe erhalten sie unter www.kellerkinder.xyz \noder wenden sie sich an support@kellerkinder.xyz -errorMode = Oh, da lief etwas falsch! Da hat jemand einen falschen Modus verwendet. \nError: mode unknow (muk)\nWeitere Hilfe erhalten sie unter www.kellerkinder.xyz \noder wenden sie sich an support@kellerkinder.xyz -errorOpenStream = Beim \u00F6ffnen des Streams ist ein Fehler aufgetreten! -errorLoad = Beim laden der Einstellungen ist ein Fehler aufgetreten! -errorSave = Beim speichern der Einstellungen ist ein Fehler aufgetreten! -noFilmFound = Kein Film mit diesem Titel gefunden! -vlcNotInstalled = Um einen Film abspielen wird der VLC Media Player ben\u00F6tigt! -infoText = \nMaintainer: seilo@kellerkinder.xyz und \nhendrik.schutter@coptersicht.de \n(c) 2016-2017 Kellerkinder www.kellerkinder.xyz - -#textFlow translations -title = Titel -year = Jahr -rating = Einstufung -publishedOn = Ver\u00F6ffentlicht am -duration = Laufzeit -genre = Gener -director = Regisseur -writer = Autor -actors = Schauspieler -plot = Beschreibung -language = Original Sprache -country = Produktionsland -awards = Auszeichnungen -metascore = Metascore -imdbRating = IMDB-Bewertung -type = Type - -firstStartHeader = Es ist kein Stammverzeichnis f\u00FCr Filme angegeben! -firstStartContent = Stammverzeichniss angeben? diff --git a/bin/resources/HomeFlix-Local_en_US.properties b/bin/resources/HomeFlix-Local_en_US.properties deleted file mode 100644 index d166f04..0000000 --- a/bin/resources/HomeFlix-Local_en_US.properties +++ /dev/null @@ -1,63 +0,0 @@ -#HomeFlix-Local_en_US.properties US-English Local and default - -#main window translations -info = Info -settings = Settings -streamingSettings = Stream Settings -tfSearch = Search... -openFolder = open Folder - -#settings translations -settingsHead1Label = HomeFlix Settings -tfPath = Path... -chooseFolder = choose Directory -mainColorLabel = main color: -fontsizeLabel = font size: -localLabel = local: -checkUpdates = check for updates -checkingUpdates = checking for updates... -updateBtnavail = update available -updateBtnNotavail = no update available -autoUpdateLabel = check at startup for updates: -version = Version: - -#column translations -columnName = Name -columnRating = Rating -columnStreamUrl = File Name -columnResolution = Resolution -columnSeason = Season -columnYear = Year - -#error translations -errorUpdateV = An error has occurred during update! \nError: could not check update version (nvc) \nTo get help, visit www.kellerkinder.xyz \nor contcat support@kellerkinder.xyz -errorUpdateD = An error has occurred during update! \nError: could not download update files (ndf) \nTo get help, visit www.kellerkinder.xyz \nor contcat support@kellerkinder.xyz -errorPlay = An error has occurred during opening the file! \nError: could not open file (nof) \nTo get help, visit www.kellerkinder.xyz \nor contcat support@kellerkinder.xyz -errorMode = Oh, something went wrong! It seems someone has used a wrong mode. \nError: mode unknow (muk) \nTo get help, visit www.kellerkinder.xyz \nor contcat support@kellerkinder.xyz -errorOpenStream = An error has occurred during opening the stream! -errorLoad = An error occurred while loading the settings! -errorSave = An error occurred while saving the settings! -noFilmFound = No film with this title found! -vlcNotInstalled = VLC Media Player is required to play a movie! -infoText = \nMaintainer: seilo@kellerkinder.xyz and \nhendrik.schutter@coptersicht.de \n(c) 2016-2017 Kellerkinder www.kellerkinder.xyz - -#textFlow translations -title = Title -year = Year -rating = Rating -publishedOn = published on -duration = Duration -genre = Gener -director = Director -writer = Writer -actors = Actors -plot = Plot -language = Language -country = Country -awards = Awards -metascore = Metascore -imdbRating = IMDB-Rating -type = Type - -firstStartHeader = There is no root directory for movies! -firstStartContent = Specify a root directory? diff --git a/build.fxbuild b/build.fxbuild deleted file mode 100644 index a7511ff..0000000 --- a/build.fxbuild +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b5a8a73 --- /dev/null +++ b/pom.xml @@ -0,0 +1,103 @@ + + 4.0.0 + + org.kellerkinder + Project-HomeFlix + 0.6.0 + jar + + Project-HomeFlix + http://www.kellerkinder.xyz + + + UTF-8 + + + + + + junit + junit + 4.11 + test + + + + commons-io + commons-io + 2.6 + + + + com.jfoenix + jfoenix + 9.0.2 + + + + com.eclipsesource.minimal-json + minimal-json + 0.9.5 + + + + org.xerial + sqlite-jdbc + 3.21.0.1 + + + + org.apache.logging.log4j + log4j-api + 2.10.0 + + + + org.apache.logging.log4j + log4j-core + 2.10.0 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + 9 + 9 + true + true + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.0 + + + package + + shade + + + true + + + kellerkinder.HomeFlix.application.Main + + + + + + + + + + + diff --git a/src/application/DBController.java b/src/application/DBController.java deleted file mode 100644 index 3b841a1..0000000 --- a/src/application/DBController.java +++ /dev/null @@ -1,634 +0,0 @@ -/** - * @author Jannik - * DBController for Project HomeFlix - * connection is in manual commit! - */ - -package application; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; - -import com.eclipsesource.json.Json; -import com.eclipsesource.json.JsonArray; -import com.eclipsesource.json.JsonObject; -import com.eclipsesource.json.JsonValue; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.text.Font; -import javafx.scene.text.FontWeight; -import javafx.scene.text.Text; - -public class DBController { - - public DBController(MainWindowController m, Main main) { - mainWindowController = m; - this.main = main; - } - - private MainWindowController mainWindowController; - private Main main; - private String DB_PATH = System.getProperty("user.home") + "\\Documents\\HomeFlix" + "\\" + "Homeflix.db"; //path to database file - private Image favorite_black = new Image("resources/icons/ic_favorite_black_18dp_1x.png"); - private Image favorite_border_black = new Image("resources/icons/ic_favorite_border_black_18dp_1x.png"); - private List filmsdbAll = new ArrayList(); - private List filmsdbLocal = new ArrayList(); - private List filmsdbStream = new ArrayList(); - private List filmsdbStreamURL = new ArrayList(); - private List filmsAll = new ArrayList(); - private List filmsDir = new ArrayList(); - private List filmsStream = new ArrayList(); - private List filmsStreamURL = new ArrayList(); - private List filmsStreamData = new ArrayList(); - Connection connection = null; - - public void main() { - if (System.getProperty("os.name").equals("Linux")) { - DB_PATH = System.getProperty("user.home") + "/HomeFlix/Homeflix.db"; - }else{ - DB_PATH = System.getProperty("user.home") + "\\Documents\\HomeFlix" + "\\" + "Homeflix.db"; - } - try { - // create a database connection - connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH); - connection.setAutoCommit(false); //AutoCommit to false -> manual commit is active - } catch (SQLException e) { - // if the error message is "out of memory", it probably means no database file is found - System.err.println(e.getMessage()); - } - - //close connection -> at the moment this kills the program -// finally { -// try { -// if (connection != null) -// connection.close(); -// } catch (SQLException e) { -// // connection close failed. -// System.err.println(e); -// } -// } - } - - void createDatabase() { - System.out.println("<==========starting loading sql==========>"); - - PreparedStatement ps; - PreparedStatement psS; - - try { - Statement stmt = connection.createStatement(); - stmt.executeUpdate("create table if not exists film_local (rating, titel, streamUrl, favIcon, cached)"); - stmt.executeUpdate("create table if not exists film_streaming (year, season, episode, rating, resolution, titel, streamUrl, favIcon, cached)"); - stmt.close(); - } catch (SQLException e1) { - e1.printStackTrace(); - } - - try { - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT * FROM film_local"); - while (rs.next()) { - filmsdbLocal.add(rs.getString(2)); - } - stmt.close(); - rs.close(); - - rs = stmt.executeQuery("SELECT * FROM film_streaming;"); - while (rs.next()) { - filmsdbStream.add(rs.getString(6)); - filmsdbStreamURL.add(rs.getString(7)); - } - stmt.close(); - rs.close(); - }catch (SQLException ea){ - System.err.println("Ups! an error occured!"); - ea.printStackTrace(); - } - - //getting all files from the selected directory TODO rework - String[] entries = new File(mainWindowController.getPath()).list(); - if(mainWindowController.getPath().equals("") || mainWindowController.getPath() == null){ - System.out.println("Kein Pfad angegeben"); //if path == null or "" - }else if(new File(mainWindowController.getPath()).exists()) { - System.out.println(entries.length); - for(int i=0;i!=entries.length;i++){ - filmsDir.add(cutOffEnd(entries[i])); - } - } else { - System.out.println(mainWindowController.getPath() + "dosen't exist!"); - } - - //getting all entries from the streaming lists - for(int v=0; v< mainWindowController.streamingData.size(); v++){ - String fileName = mainWindowController.getStreamingPath()+"/"+mainWindowController.streamingData.get(v).getStreamUrl(); - try { - JsonObject object = Json.parse(new FileReader(fileName)).asObject(); - JsonArray items = object.get("entries").asArray(); - for (JsonValue item : items) { - filmsStream.add(item.asObject().getString("titel","")); - filmsStreamURL.add(item.asObject().getString("streamUrl","")); - filmsStreamData.add(fileName); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - //add all entries to filmsAll and filmsdbAl, for later comparing - filmsAll.addAll(filmsDir); - filmsAll.addAll(filmsStream); - filmsdbAll.addAll(filmsdbLocal); - filmsdbAll.addAll(filmsdbStream); - System.out.println("films in directory: "+filmsAll.size()); - System.out.println("filme in db: "+filmsdbAll.size()); - - /** - * if filmsdbAll.size() == 0 database is empty, we need to fill it - * else check if there is something to remove or to add - * TODO separate local and streaming for better error handling - */ - if(filmsdbAll.size() == 0){ - System.out.println("creating entries ..."); - - try{ - ps = connection.prepareStatement("insert into film_local values (?, ?, ?, ?, ?)"); - psS = connection.prepareStatement("insert into film_streaming values (?, ?, ?, ?, ?, ?, ?, ?, ?)"); - - if(mainWindowController.getPath().equals("") || mainWindowController.getPath() == null){ - System.out.println("Kein Pfad angegeben"); //if path == null or "" - }else if(new File(mainWindowController.getPath()).exists()){ - for(int j=0;j!=entries.length;j++) //goes through all the files in the directory - { - ps.setInt(1, 0); //rating as integer 1. column - ps.setString(2, cutOffEnd(entries[j])); //name as String without ending 2. column - ps.setString(3,entries[j]); //path as String 3. column - ps.setString(4, "favorite_border_black"); - ps.setBoolean(5, false); - ps.addBatch(); // add command to prepared statement - } - } - - if(mainWindowController.getStreamingPath().equals("")||mainWindowController.getStreamingPath().equals(null)){ - System.out.println("Kein Pfad angegeben"); //if path == null or "" - }else{ - for(int i=0; i< mainWindowController.streamingData.size(); i++){ - String fileNamea = mainWindowController.getStreamingPath()+"/"+mainWindowController.streamingData.get(i).getStreamUrl(); - try { - JsonObject object = Json.parse(new FileReader(fileNamea)).asObject(); - JsonArray items = object.get("entries").asArray(); - for (JsonValue item : items) { - psS.setInt(1, item.asObject().getInt("year", 0)); - psS.setInt(2, item.asObject().getInt("season", 0)); - psS.setInt(3, item.asObject().getInt("episode", 0)); - psS.setInt(4, 0); - psS.setString(5, item.asObject().getString("resolution", "")); - psS.setString(6, item.asObject().getString("titel","")); - psS.setString(7, item.asObject().getString("streamUrl", "")); - psS.setString(8, "favorite_border_black"); - psS.setBoolean(9, false); - psS.addBatch(); // add command to prepared statement - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } - ps.executeBatch(); //execute statement to write entries into table - psS.executeBatch(); - connection.commit(); - ps.close(); - psS.close(); - }catch (SQLException ea) { - System.err.println("Ups! an error occured!"); - ea.printStackTrace(); - } - }else { - try { - try { - checkAddEntry(); //check if added a new file - } catch (IOException e) { - e.printStackTrace(); - } - checkRemoveEntry(); //check if removed a file - } catch (SQLException e) { - e.printStackTrace(); - } - } - - //start of cache-table - try { - Statement stmt = connection.createStatement(); - stmt.executeUpdate( "create table if not exists cache (streamUrl, Title, Year, Rated, Released, Runtime, Genre, Director, Writer," //streamUrl is primary key - +" Actors, Plot, Language, Country, Awards, Metascore, imdbRating, imdbVotes, imdbID, Type, Poster, Response)"); - stmt.close(); - } catch (SQLException e1) { - e1.printStackTrace(); - } - - } - - //loading data from database to mainWindowController - void loadData(){ - System.out.println("loading data to mwc ..."); - try { - //load local Data - Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT * FROM film_local ORDER BY titel"); - while (rs.next()) { - if(rs.getString(4).equals("favorite_black")){ - mainWindowController.localFilms.add( new tableData(1, 1, 1, rs.getDouble(1), "1", rs.getString(2), rs.getString(3), new ImageView(favorite_black),rs.getBoolean(5))); - }else{ - mainWindowController.localFilms.add( new tableData(1, 1, 1, rs.getDouble(1), "1", rs.getString(2), rs.getString(3), new ImageView(favorite_border_black),rs.getBoolean(5))); - } - } - stmt.close(); - rs.close(); - - //load streaming Data FIXME check if there are streaming data before loading -> maybe there is an issue now - rs = stmt.executeQuery("SELECT * FROM film_streaming ORDER BY titel;"); - while (rs.next()) { - if(rs.getString(8).equals("favorite_black")){ - mainWindowController.streamingFilms.add(new tableData(rs.getInt(1), rs.getInt(2), rs.getInt(3), rs.getDouble(4), rs.getString(5), rs.getString(6), rs.getString(7), new ImageView(favorite_black),rs.getBoolean(9))); - }else{ - mainWindowController.streamingFilms.add(new tableData(rs.getInt(1), rs.getInt(2), rs.getInt(3), rs.getDouble(4), rs.getString(5), rs.getString(6), rs.getString(7), new ImageView(favorite_border_black),rs.getBoolean(9))); - } - } - stmt.close(); - rs.close(); - } catch (SQLException e) { - System.err.println("Ups! an error occured!"); - e.printStackTrace(); - } - System.out.println("<==========finished loading sql==========>"); - } - - //Refreshes the data in mainWindowController.newDaten and mainWindowController.streamData - //FIXME it seems that there is an issue at the moment with streaming refreshing wrong entry if there is more than one with the same name - void refresh(String name,int i) throws SQLException{ - System.out.println("refresh ..."); - Statement stmt; - - try { - stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT * FROM film_local WHERE titel = \""+name+"\";" ); - if(rs.getString(4).equals("favorite_black")){ - mainWindowController.localFilms.set(i, new tableData(1, 1, 1, rs.getDouble(1), "1", rs.getString(2), rs.getString(3), new ImageView(favorite_black),rs.getBoolean(5))); - }else{ - mainWindowController.localFilms.set(i, new tableData(1, 1, 1, rs.getDouble(1), "1", rs.getString(2), rs.getString(3), new ImageView(favorite_border_black),rs.getBoolean(5))); - } - stmt.close(); - rs.close(); - } catch (SQLException e) { - try { - stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT * FROM film_streaming WHERE titel = \""+name+"\";" ); - if(rs.getString(8).equals("favorite_black")){ - mainWindowController.streamingFilms.set(i,new tableData(rs.getInt(1), rs.getInt(2), rs.getInt(3), rs.getDouble(4), rs.getString(5), rs.getString(6), rs.getString(7), new ImageView(favorite_black),rs.getBoolean(9))); - }else{ - mainWindowController.streamingFilms.set(i,new tableData(rs.getInt(1), rs.getInt(2), rs.getInt(3), rs.getDouble(4), rs.getString(5), rs.getString(6), rs.getString(7), new ImageView(favorite_border_black),rs.getBoolean(9))); - } - stmt.close(); - rs.close(); - } catch (SQLException e1) { - System.err.println("Ups! an error occured!"); - e1.printStackTrace(); - } - } - } - /** - * check if there are any entries that have been removed from the film-directory - * @throws SQLException - */ - private void checkRemoveEntry() throws SQLException{ - System.out.println("checking for entrys to remove to DB ..."); - Statement stmt = connection.createStatement(); - - for(int a=0; a nameText = new ArrayList(); - ArrayList responseText = new ArrayList(); - String fontFamily = main.getFONT_FAMILY(); - Image im; - int fontSize = (int) Math.round(mainWindowController.size); - int j=2; - - nameText.add(0, new Text(mainWindowController.title+": ")); - nameText.add(1, new Text(mainWindowController.year+": ")); - nameText.add(2, new Text(mainWindowController.rating+": ")); - nameText.add(3, new Text(mainWindowController.publishedOn+": ")); - nameText.add(4, new Text(mainWindowController.duration+": ")); - nameText.add(5, new Text(mainWindowController.genre+": ")); - nameText.add(6, new Text(mainWindowController.director+": ")); - nameText.add(7, new Text(mainWindowController.writer+": ")); - nameText.add(8, new Text(mainWindowController.actors+": ")); - nameText.add(9, new Text(mainWindowController.plot+": ")); - nameText.add(10, new Text(mainWindowController.language+": ")); - nameText.add(11, new Text(mainWindowController.country+": ")); - nameText.add(12, new Text(mainWindowController.awards+": ")); - nameText.add(13, new Text(mainWindowController.metascore+": ")); - nameText.add(14, new Text(mainWindowController.imdbRating+": ")); - nameText.add(15, new Text(mainWindowController.type+": ")); - - for(int i=0; i<15; i++){ - responseText.add(new Text(rs.getString(j)+"\n")); - j++; - } - responseText.add(new Text(rs.getString(19)+"\n")); - im = new Image(new File(rs.getString(20)).toURI().toString()); - - stmt.close(); - rs.close(); - - for(int i=0; i - * - * 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 application; - -import java.io.File; -import java.io.IOException; -import java.util.Locale; -import java.util.Optional; -import java.util.ResourceBundle; -import javafx.application.Application; -import javafx.fxml.FXMLLoader; -import javafx.scene.Scene; -import javafx.scene.control.Alert; -import javafx.scene.control.Alert.AlertType; -import javafx.scene.control.ButtonType; -import javafx.scene.image.Image; -import javafx.scene.layout.AnchorPane; -import javafx.stage.DirectoryChooser; -import javafx.stage.Stage; - -public class Main extends Application { - - Stage primaryStage; - private String path; - String currentWorkingDirectory; - private String COLOR = "ee3523"; - private String FONT_FAMILY = "System"; - private String mode = "local"; //local or streaming TODO - private String local = System.getProperty("user.language")+"_"+System.getProperty("user.country"); - private boolean AUTO_UPDATE = false; - private double FONT_SIZE = 17; - private ResourceBundle bundle; - private MainWindowController mainWindowController; - private File directory; - private File settingsFile; - private File posterCache; - private String dirWin = System.getProperty("user.home") + "/Documents/HomeFlix"; //Windows: C:/Users/"User"/Documents/HomeFlix - private String dirLinux = System.getProperty("user.home") + "/HomeFlix"; //Linux: /home/"User"/HomeFlix - - @Override - public void start(Stage primaryStage) throws IOException { - currentWorkingDirectory = new java.io.File( "." ).getCanonicalPath(); - this.primaryStage = primaryStage; - mainWindow(); - } - - private void mainWindow(){ - - try { - FXMLLoader loader = new FXMLLoader(Main.class.getResource("MainWindow.fxml")); - AnchorPane pane = loader.load(); - primaryStage.setMinHeight(600.00); - primaryStage.setMinWidth(900.00); - primaryStage.setResizable(false); - primaryStage.setTitle("Project HomeFlix"); - primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/resources/Homeflix_Icon_64x64.png"))); //adds application icon - - mainWindowController = loader.getController(); //Link of FXMLController and controller class - mainWindowController.setAutoUpdate(AUTO_UPDATE); //set auto-update - mainWindowController.setCurrentWorkingDirectory(currentWorkingDirectory); - mainWindowController.setMain(this); //call setMain - - /**Linux else Windows, check if directory & config exist - * Windows: config file: C:/Users/"User"/Documents/HomeFlix/config.xml - * directory: C:/Users/"User"/Documents/HomeFlix - * Linux: config file: /home/"User"/HomeFlix/config.xml - * directory: /home/"User"/HomeFlix - */ - if(System.getProperty("os.name").equals("Linux")) { - directory = new File(dirLinux); - settingsFile = new File(dirLinux + "/config.xml"); - } else { - directory = new File(dirWin); - settingsFile = new File(dirWin + "/config.xml"); - } - - posterCache = new File(directory+"/posterCache"); - - if(!settingsFile.exists()){ - directory.mkdir(); - mainWindowController.setPath(firstStart()); - mainWindowController.setStreamingPath(directory.getAbsolutePath()); - mainWindowController.setColor(COLOR); - mainWindowController.setSize(FONT_SIZE); - mainWindowController.setAutoUpdate(AUTO_UPDATE); - mainWindowController.setLocal(local); - mainWindowController.setMode(mode); - mainWindowController.saveSettings(); - Runtime.getRuntime().exec("java -jar ProjectHomeFlix.jar"); //start again (preventing Bugs) - System.exit(0); //finishes it self - } - - if(!posterCache.exists()) { - posterCache.mkdir(); - } - - mainWindowController.loadSettings(); - mainWindowController.loadStreamingSettings(); - mainWindowController.initUI(); - mainWindowController.initActions(); - mainWindowController.initTabel(); - mainWindowController.setLocalUI(); - mainWindowController.applyColor(); //set theme color - - mainWindowController.dbController.main(); //initialize database controller - mainWindowController.dbController.createDatabase(); //creating the database - mainWindowController.dbController.loadData(); //loading data from database to mainWindowController - mainWindowController.addDataUI(); - - Scene scene = new Scene(pane); //create new scene, append pane to scene - scene.getStylesheets().add(Main.class.getResource("MainWindow.css").toExternalForm()); - primaryStage.setScene(scene); //append scene to stage - primaryStage.show(); //show stage - } catch (IOException e) { - e.printStackTrace(); - } - } - - //Method for first Start - private String firstStart(){ - MainWindowController.firststart = true; - switch(System.getProperty("user.language")+"_"+System.getProperty("user.country")){ - case "en_US": bundle = ResourceBundle.getBundle("resources.HomeFlix-Local", Locale.US); //us_english - break; - case "de_DE": bundle = ResourceBundle.getBundle("resources.HomeFlix-Local", Locale.GERMAN); //German - break; - default: bundle = ResourceBundle.getBundle("resources.HomeFlix-Local", Locale.US); //default local - break; - } - - Alert alert = new Alert(AlertType.CONFIRMATION); //new alert with file-chooser - alert.setTitle("Project HomeFlix"); - alert.setHeaderText(bundle.getString("firstStartHeader")); - alert.setContentText(bundle.getString("firstStartContent")); - - Optional result = alert.showAndWait(); - if (result.get() == ButtonType.OK){ - DirectoryChooser directoryChooser = new DirectoryChooser(); - File selectedDirectory = - directoryChooser.showDialog(primaryStage); - path = selectedDirectory.getAbsolutePath(); - - } else { - path = ""; - } - return path; - } - - public static void main(String[] args) { - launch(args); - } - - public String getFONT_FAMILY() { - return FONT_FAMILY; - } - - public void setFONT_FAMILY(String FONT_FAMILY) { - this.FONT_FAMILY = FONT_FAMILY; - } - - public File getPosterCache() { - return posterCache; - } - - public void setPosterCache(File posterCache) { - this.posterCache = posterCache; - } -} \ No newline at end of file diff --git a/src/application/MainWindow.css b/src/application/MainWindow.css deleted file mode 100644 index cb1165b..0000000 --- a/src/application/MainWindow.css +++ /dev/null @@ -1,4 +0,0 @@ -.jfx-hamburgerW StackPane { -fx-background-color: white; - -fx-background-radius: 5px; } -.jfx-hamburgerB StackPane { -fx-background-color: black; - -fx-background-radius: 5px; } \ No newline at end of file diff --git a/src/application/MainWindow.fxml b/src/application/MainWindow.fxml deleted file mode 100644 index 032c390..0000000 --- a/src/application/MainWindow.fxml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/application/MainWindowController.java b/src/application/MainWindowController.java deleted file mode 100644 index 1b72bb1..0000000 --- a/src/application/MainWindowController.java +++ /dev/null @@ -1,1163 +0,0 @@ -/** - * Project HomeFlix - * - * Copyright 2016-2017 - * - * 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 application; - -import java.awt.Desktop; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.math.BigInteger; -import java.net.URI; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Locale; -import java.util.Properties; -import java.util.ResourceBundle; -import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXColorPicker; -import com.jfoenix.controls.JFXHamburger; -import com.jfoenix.controls.JFXSlider; -import com.jfoenix.controls.JFXTextField; -import com.jfoenix.controls.JFXToggleButton; -import com.jfoenix.transitions.hamburger.HamburgerBackArrowBasicTransition; - -import javafx.animation.FadeTransition; -import javafx.animation.ParallelTransition; -import javafx.animation.TranslateTransition; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.fxml.FXML; -import javafx.scene.control.Alert; -import javafx.scene.control.Alert.AlertType; -import javafx.scene.control.ChoiceBox; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.Label; -import javafx.scene.control.MenuItem; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableView; -import javafx.scene.control.TextArea; -import javafx.scene.control.TreeItem; -import javafx.scene.control.TreeTableColumn; -import javafx.scene.control.TreeTableColumn.SortType; -import javafx.scene.control.TreeTableView; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.GridPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import javafx.scene.paint.Color; -import javafx.scene.text.Font; -import javafx.scene.text.TextFlow; -import javafx.stage.DirectoryChooser; -import javafx.util.Duration; - -public class MainWindowController { - @FXML - private AnchorPane anpane; - @FXML - private AnchorPane settingsAnchor; - @FXML - private AnchorPane streamingSettingsAnchor; - @FXML - private HBox topHBox; - @FXML - private VBox sideMenuVBox; - @FXML - private TreeTableView treeTableViewfilm; - @FXML - private TableView tableViewStreamingdata; - @FXML - TextFlow textFlow; - @FXML - ScrollPane scrollPane; - @FXML - private JFXButton playbtn; - @FXML - private JFXButton openfolderbtn; - @FXML - private JFXButton returnBtn; - @FXML - private JFXButton forwardBtn; - @FXML - private JFXButton infoBtn; - @FXML - private JFXButton settingsBtn; - @FXML - private JFXButton streamingSettingsBtn; - @FXML - private JFXButton switchBtn; - @FXML - private JFXButton debugBtn; - @FXML - public JFXButton updateBtn; - @FXML - private JFXButton directoryBtn; - @FXML - private JFXButton streamingDirectoryBtn; - @FXML - private JFXHamburger menuHam; - @FXML - private JFXToggleButton autoupdateBtn; - @FXML - public JFXTextField tfPath; - @FXML - public JFXTextField tfStreamingPath; - @FXML - private JFXTextField tfsearch; - @FXML - public JFXColorPicker mainColor; - @FXML - public ChoiceBox cbLocal = new ChoiceBox<>(); - @FXML - public JFXSlider sliderFontSize; - @FXML - private Label versionLabel; - @FXML - private Label fontsizeLabel; - @FXML - private Label autoUpdateLabel; - @FXML - private Label settingsHead1Label; - @FXML - private Label mainColorLabel; - @FXML - private Label localLabel; - @FXML - ImageView image1; - - private ImageView imv1; - - @FXML - TreeItem root = new TreeItem<>(new tableData(1, 1, 1, 5.0,"1", "filme","1", imv1, false)); - @FXML - TreeTableColumn columnRating = new TreeTableColumn<>("Rating"); - @FXML - TreeTableColumn columnTitel = new TreeTableColumn<>("Titel"); - @FXML - TreeTableColumn columnStreamUrl = new TreeTableColumn<>("File Name"); - @FXML - TreeTableColumn columnResolution = new TreeTableColumn<>("Resolution"); - @FXML - TreeTableColumn columnYear = new TreeTableColumn<>("Year"); - @FXML - TreeTableColumn columnSeason = new TreeTableColumn<>("Season"); - @FXML - TreeTableColumn columnEpisode = new TreeTableColumn<>("Episode"); - - @FXML - private TreeItem streamingRoot =new TreeItem<>(new tableData(1 ,1 ,1 ,1.0 ,"1" ,"filme" ,"1", imv1, false)); - @FXML - private TableColumn dataNameColumn = new TableColumn<>("Datei Name"); - @FXML - private TableColumn dataNameEndColumn = new TableColumn<>("Datei Name mit Endung"); - - private boolean menuTrue = false; //saves the position of menuBtn (opened or closed) - private boolean settingsTrue = false; - private boolean streamingSettingsTrue = false; - private boolean autoUpdate = false; - static boolean firststart = false; - private int hashA = -2055934614; - private String version = "0.5.2"; - private String buildNumber = "129"; - private String versionName = "solidify cow"; - private File dirWin = new File(System.getProperty("user.home") + "/Documents/HomeFlix"); - private File dirLinux = new File(System.getProperty("user.home") + "/HomeFlix"); - private File fileWin = new File(dirWin + "/config.xml"); - private File fileLinux = new File(dirLinux + "/config.xml"); - - String errorUpdateD; - String errorUpdateV; - String noFilmFound; - private String errorPlay; - private String errorOpenStream; - private String errorMode; - private String errorLoad; - private String errorSave; - private String infoText; - private String vlcNotInstalled; - private String currentWorkingDirectory; - private String path; - private String streamingPath; - private String color; - private String name; - private String datPath; - private String mode; - @SuppressWarnings("unused") - private String ratingSortType; - private String local; - String title; - String year; - String rating; - String publishedOn; - String duration; - String genre; - String director; - String writer; - String actors; - String plot; - String language; - String country; - String awards; - String metascore; - String imdbRating; - String type; - double size; - private int last; - private int selected; - private int next; - private File selectedFolder; - private File selectedStreamingFolder; - ResourceBundle bundle; - - private ObservableList filterData = FXCollections.observableArrayList(); - private ObservableList locals = FXCollections.observableArrayList("English (en_US)", "Deutsch (de_DE)"); - ObservableList localFilms = FXCollections.observableArrayList(); - ObservableList streamingFilms = FXCollections.observableArrayList(); - ObservableList streamingData = FXCollections.observableArrayList(); - private ImageView skip_previous_white = new ImageView(new Image("resources/icons/ic_skip_previous_white_18dp_1x.png")); - private ImageView skip_previous_black = new ImageView(new Image("resources/icons/ic_skip_previous_black_18dp_1x.png")); - private ImageView skip_next_white = new ImageView(new Image("resources/icons/ic_skip_next_white_18dp_1x.png")); - private ImageView skip_next_black = new ImageView(new Image("resources/icons/ic_skip_next_black_18dp_1x.png")); - private ImageView play_arrow_white = new ImageView(new Image("resources/icons/ic_play_arrow_white_18dp_1x.png")); - private ImageView play_arrow_black = new ImageView(new Image("resources/icons/ic_play_arrow_black_18dp_1x.png")); - private DirectoryChooser directoryChooser = new DirectoryChooser(); - private MenuItem like = new MenuItem("like"); - private MenuItem dislike = new MenuItem("dislike"); //TODO one option (like or dislike) - private ContextMenu menu = new ContextMenu(like, dislike); - Properties props = new Properties(); - - private Main main; - private updater Updater; - private apiQuery ApiQuery; - DBController dbController; - - @FXML - private void playbtnclicked(){ - System.out.println(System.getProperty("os.name")); - if(System.getProperty("os.name").contains("Linux")){ - System.out.println("This is "+System.getProperty("os.name")); - String line; - String output = ""; - Process p; - try { - p = Runtime.getRuntime().exec("which vlc"); - BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); - while ((line = input.readLine()) != null) { - output = line; - } - System.out.println(output); - input.close(); - } catch (IOException e1) { - e1.printStackTrace(); - } - if(output.contains("which: no vlc")||output == ""){ - Alert alert = new Alert(AlertType.INFORMATION); - alert.setHeaderText(""); - alert.setTitle("Info"); - alert.setContentText(vlcNotInstalled); - alert.showAndWait(); - }else{ - try { - Runtime.getRuntime().exec(new String[] { "vlc", getPath()+"/"+ datPath}); - } catch (IOException e) { - showErrorMsg(errorPlay,e); - } - } - }else if(System.getProperty("os.name").contains("Windows") || System.getProperty("os.name").contains("Mac OS X")){ - System.out.println("This is "+System.getProperty("os.name")); - if(mode.equals("local")){ - try { - Desktop.getDesktop().open(new File(getPath()+"\\"+ datPath)); - } catch (IOException e) { - showErrorMsg(errorPlay,e); - } - }else if(mode.equals("streaming")){ - try { - Desktop.getDesktop().browse(new URI(datPath)); //open the streaming URL in browser - } catch (URISyntaxException | IOException e) { - showErrorMsg(errorOpenStream, (IOException) e); - } - }else{ - IOException e = new IOException("error"); - showErrorMsg(errorMode, e); - - } - } - } - - @FXML - private void openfolderbtnclicked(){ - try { - Desktop.getDesktop().open(new File(getPath())); //open path when button is clicked - } catch (IOException e) { - e.printStackTrace(); - } - } - - @FXML - private void returnBtnclicked(){ - treeTableViewfilm.getSelectionModel().select(last); - } - - @FXML - private void forwardBtnclicked(){ - treeTableViewfilm.getSelectionModel().select(next); - } - - @FXML - private void infoBtnclicked(){ - Alert alert = new Alert(AlertType.INFORMATION); - alert.setTitle("Info"); - alert.setHeaderText("Project HomeFlix"); - alert.setContentText(infoText); - alert.initOwner(main.primaryStage); - alert.showAndWait(); - } - - @FXML - private void settingsBtnclicked(){ - if(settingsTrue == false){ - if(streamingSettingsTrue == true){ - streamingSettingsAnchor.setVisible(false); - streamingSettingsTrue = false; - } - settingsAnchor.setVisible(true); - settingsTrue = true; - }else{ - settingsAnchor.setVisible(false); - setPath(tfPath.getText()); - saveSettings(); - settingsTrue = false; - } - } - - /** - * TODO additional info about the "streaming.json" - */ - @FXML - private void streamingSettingsBtnclicked(){ - if(streamingSettingsTrue == false){ - if(settingsTrue == true){ - settingsAnchor.setVisible(false); - settingsTrue = false; - } - streamingSettingsAnchor.setVisible(true); - streamingSettingsTrue = true; - }else{ - streamingSettingsAnchor.setVisible(false); - streamingSettingsTrue = false; - } - } - - @FXML - private void switchBtnclicked(){ - if(mode.equals("local")){ //switch to streaming mode - setMode("streaming"); - switchBtn.setText("local"); - }else if(mode.equals("streaming")){ //switch to local mode - setMode("local"); - switchBtn.setText("streaming"); - } - saveSettings(); - root.getChildren().remove(0,root.getChildren().size()); - addDataUI(); - settingsAnchor.setVisible(false); - streamingSettingsAnchor.setVisible(false); - sideMenuSlideOut(); //disables side-menu - menuTrue = false; - settingsTrue = false; - streamingSettingsTrue = false; - } - - @FXML - private void debugBtnclicked(){ - //for testing - } - - - @FXML - private void tfPathAction(){ - setPath(tfPath.getText()); - saveSettings(); - } - - @FXML - private void directoryBtnAction(){ - selectedFolder = directoryChooser.showDialog(null); - if(selectedFolder == null){ - System.out.println("No Directory selected"); - }else{ - setPath(selectedFolder.getAbsolutePath()); - saveSettings(); - tfPath.setText(getPath()); - try { - Runtime.getRuntime().exec("java -jar ProjectHomeFlix.jar"); //start again - System.exit(0); //finishes itself - } catch (IOException e) { - System.out.println("es ist ein Fehler aufgetreten"); - e.printStackTrace(); - } - } - } - - @FXML - private void mainColorAction(){ - editColor(mainColor.getValue().toString()); - applyColor(); - } - - @FXML - private void updateBtnAction(){ - Thread updateThread = new Thread(Updater); - updateThread.setName("Updater"); - updateThread.start(); - } - - @FXML - private void autoupdateBtnAction(){ - if(autoUpdate){ - setAutoUpdate(false); - }else{ - setAutoUpdate(true); - } - saveSettings(); - } - - @FXML - private void tfStreamingPathAction(){ - // - } - - @FXML - private void streamingDirectoryBtnAction(){ - selectedStreamingFolder = directoryChooser.showDialog(null); - if(selectedStreamingFolder == null){ - System.out.println("No Directory selected"); - }else{ - setStreamingPath(selectedStreamingFolder.getAbsolutePath()); - saveSettings(); - tfStreamingPath.setText(getStreamingPath()); - try { - Runtime.getRuntime().exec("java -jar ProjectHomeFlix.jar"); //start again - System.exit(0); //finishes itself - } catch (IOException e) { - System.out.println("es ist ein Fehler aufgetreten"); - e.printStackTrace(); - } - } - } - - - /**"Main" Method called in Main.java main() when starting - * Initialize other objects: Updater, dbController and ApiQuery - */ - void setMain(Main main) { - this.main = main; - Updater = new updater(this, buildNumber); - dbController = new DBController(this, this.main); - ApiQuery = new apiQuery(this, dbController, this.main); - } - - //Initialize the tables (treeTableViewfilm and tableViewStreamingdata) - @SuppressWarnings({ "unchecked"}) //TODO - void initTabel(){ - - //film Table - columnRating.setMaxWidth(80); - columnTitel.setMaxWidth(260); - columnStreamUrl.setMaxWidth(0); - dataNameColumn.setPrefWidth(150); - dataNameEndColumn.setPrefWidth(220); - columnRating.setStyle("-fx-alignment: CENTER;"); - - treeTableViewfilm.setRoot(root); - treeTableViewfilm.setColumnResizePolicy( TreeTableView.CONSTRAINED_RESIZE_POLICY ); - treeTableViewfilm.setShowRoot(false); - - //write content into cell - columnTitel.setCellValueFactory(cellData -> cellData.getValue().getValue().titleProperty()); - columnRating.setCellValueFactory(cellData -> cellData.getValue().getValue().imageProperty()); - columnStreamUrl.setCellValueFactory(cellData -> cellData.getValue().getValue().streamUrlProperty()); - columnResolution.setCellValueFactory(cellData -> cellData.getValue().getValue().resolutionProperty()); - columnYear.setCellValueFactory(cellData -> cellData.getValue().getValue().yearProperty().asObject()); - columnSeason.setCellValueFactory(cellData -> cellData.getValue().getValue().seasonProperty().asObject()); - columnEpisode.setCellValueFactory(cellData -> cellData.getValue().getValue().episodeProperty().asObject()); - - treeTableViewfilm.getColumns().addAll(columnTitel, columnRating, columnStreamUrl, columnResolution, columnYear, columnSeason, columnEpisode); - treeTableViewfilm.getColumns().get(2).setVisible(false); //hide columnStreamUrl (column with file path important for the player) - - //Change-listener for TreeTable - treeTableViewfilm.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, Object oldVal, Object newVal){ - // last = selected; //for auto-play - selected = treeTableViewfilm.getSelectionModel().getSelectedIndex(); //get selected item - last = selected - 1; - next = selected + 1; - name = columnTitel.getCellData(selected); //get name of selected item - datPath = columnStreamUrl.getCellData(selected); //get file path of selected item - - if(mode.equals("local")){ - if(localFilms.get(selected).getCached()==true){ - System.out.println("loading from cache: "+name); - dbController.readCache(datPath); - }else{ - ApiQuery.startQuery(name,datPath); // start api query - } - }else{ - System.out.println(streamingFilms.size()); - if(streamingFilms.get(selected).getCached()==true){ - System.out.println("loading from cache: "+name); - dbController.readCache(datPath); - }else{ - ApiQuery.startQuery(name,datPath); // start api query - } - } - } - }); - - //context menu for treetableview - treeTableViewfilm.setContextMenu(menu); - - //Streaming-Settings Table - dataNameColumn.setCellValueFactory(cellData -> cellData.getValue().titleProperty()); - dataNameEndColumn.setCellValueFactory(cellData -> cellData.getValue().streamUrlProperty()); - - tableViewStreamingdata.getColumns().addAll(dataNameColumn, dataNameEndColumn); - tableViewStreamingdata.setItems(streamingData); - } - - //Initializing the actions - void initActions(){ - - HamburgerBackArrowBasicTransition burgerTask = new HamburgerBackArrowBasicTransition(menuHam); - menuHam.addEventHandler(MouseEvent.MOUSE_PRESSED, (e)->{ - if(menuTrue == false){ - sideMenuSlideIn(); - burgerTask.setRate(1.0); - burgerTask.play(); - menuTrue = true; - }else{ - sideMenuSlideOut(); - burgerTask.setRate(-1.0); - burgerTask.play(); - menuTrue = false; - } - if(settingsTrue == true){ - settingsAnchor.setVisible(false); - setPath(tfPath.getText()); - saveSettings(); - settingsTrue = false; - } - if(streamingSettingsTrue == true){ - streamingSettingsAnchor.setVisible(false); - streamingSettingsTrue = false; - } - - }); - - tfsearch.textProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable,String oldValue, String newValue) { - ObservableList helpData; - filterData.removeAll(filterData); - root.getChildren().remove(0,root.getChildren().size()); - - if(mode.equals("local")){ - helpData = localFilms; - }else{ - helpData = streamingFilms; - } - - for(int i = 0; i < helpData.size(); i++){ - if(helpData.get(i).getTitle().toLowerCase().contains(tfsearch.getText().toLowerCase())){ - filterData.add(helpData.get(i)); //add data from newDaten to filteredData where title contains search input - } - } - - for(int i = 0; i < filterData.size(); i++){ - root.getChildren().add(new TreeItem(filterData.get(i))); //add filtered data to root node after search - } - if(tfsearch.getText().hashCode() == hashA){ - setColor("000000"); - applyColor(); - } - } - }); - - cbLocal.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener() { - public void changed(ObservableValue ov, Number value, Number new_value) { - String local = cbLocal.getItems().get((int) new_value).toString(); - local = local.substring(local.length()-6,local.length()-1); //reading only en_US from English (en_US) - setLocal(local); - setLocalUI(); - saveSettings(); - } - }); - - sliderFontSize.valueProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue ov,Number old_val, Number new_val) { - setSize(sliderFontSize.getValue()); - - if(name != null){ - dbController.readCache(datPath); - } - -// ta1.setFont(Font.font("System", size)); - saveSettings(); - } - }); - - like.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - if(mode.equals("streaming")){ - dbController.like(name,streamingFilms.get(selected).getStreamUrl()); - }else{ - dbController.like(name,localFilms.get(selected).getStreamUrl()); - } - dbController.getFavStatus(name); - try { - dbController.refresh(name, selected); - } catch (SQLException e) { - Alert alert = new Alert(AlertType.ERROR); - alert.setTitle("Error"); - alert.setHeaderText(""); - alert.setContentText("There should be an error message in the future (like problem)\nIt seems as a cat has stolen the like-methode"); - e.printStackTrace(); - } - refreshTable(); - } - }); - - dislike.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - if(mode.equals("streaming")){ - dbController.dislike(name,streamingFilms.get(selected).getStreamUrl()); - }else{ - dbController.dislike(name,localFilms.get(selected).getStreamUrl()); - } - dbController.getFavStatus(name); - try { - dbController.refresh(name, selected); - } catch (SQLException e) { - Alert alert = new Alert(AlertType.ERROR); - alert.setTitle("Error"); - alert.setHeaderText(""); - alert.setContentText("There should be an error message in the future (dislike problem)"); - e.printStackTrace(); - } - refreshTable(); - } - }); - - /** - * FIXME fix bug when sort by ASCENDING, wrong order - */ - columnRating.sortTypeProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue paramObservableValue, SortType paramT1, SortType paramT2) { - System.out.println("NAME Clicked -- sortType = " + paramT1 + ", SortType=" + paramT2); - ArrayList fav_true = new ArrayList(); - ArrayList fav_false = new ArrayList(); - ObservableList helpData; - filterData.removeAll(filterData); -// treeTableViewfilm.getSelectionModel().clearSelection(selected); - root.getChildren().remove(0,root.getChildren().size()); - - if(mode.equals("local")){ - helpData = localFilms; - }else{ - helpData = streamingFilms; - } - - - for(int i = 0;i(filterData.get(i))); //add filtered data to root node after search - } - } - }); - } - - //initialize UI elements - void initUI(){ - System.out.println("Mode: "+mode); //TODO debugging - debugBtn.setDisable(true); //debugging button for tests - debugBtn.setVisible(false); - - tfPath.setText(getPath()); - sliderFontSize.setValue(getSize()); - mainColor.setValue(Color.valueOf(getColor())); - - updateBtn.setFont(Font.font("System", 12)); - cbLocal.setItems(locals); - - if(autoUpdate){ - autoupdateBtn.setSelected(true); - try { - Thread updateThread = new Thread(Updater); - updateThread.setName("Updater"); - updateThread.start(); - updateThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }else{ - autoupdateBtn.setSelected(false); - } - } - - private void refreshTable(){ - if(mode.equals("local")){ - root.getChildren().set(selected, new TreeItem(localFilms.get(selected))); - }else if(mode.equals("streaming")){ - root.getChildren().set(selected, new TreeItem(streamingFilms.get(selected))); - } - } - - void addDataUI(){ - if(mode.equals("local")){ - for(int i = 0; i < localFilms.size(); i++){ - root.getChildren().add(new TreeItem(localFilms.get(i))); //add data to root-node - } - columnRating.setMaxWidth(85); - columnTitel.setMaxWidth(290); - treeTableViewfilm.getColumns().get(3).setVisible(false); - treeTableViewfilm.getColumns().get(4).setVisible(false); - treeTableViewfilm.getColumns().get(5).setVisible(false); - treeTableViewfilm.getColumns().get(6).setVisible(false); - }else if(mode.equals("streaming")){ - for(int i = 0; i < streamingFilms.size(); i++){ - root.getChildren().add(new TreeItem(streamingFilms.get(i))); //add data to root-node - } - columnTitel.setMaxWidth(150); - columnResolution.setMaxWidth(65); - columnRating.setMaxWidth(50); - columnYear.setMaxWidth(43); - columnSeason.setMaxWidth(42); - columnEpisode.setMaxWidth(44); - treeTableViewfilm.getColumns().get(3).setVisible(true); - treeTableViewfilm.getColumns().get(4).setVisible(true); - treeTableViewfilm.getColumns().get(5).setVisible(true); - treeTableViewfilm.getColumns().get(6).setVisible(true); - } - } - - void loadStreamingSettings(){ - if(getStreamingPath().equals("")||getStreamingPath().equals(null)){ - System.out.println("Kein Pfad angegeben"); //if path equals "" or null - }else{ - String[] entries = new File(getStreamingPath()).list(); - for(int i = 0; i < entries.length; i++){ - if(entries[i].endsWith(".json")){ - String titel = ohneEndung(entries[i]); - String data = entries[i]; - streamingData.add(new tableData(1,1,1,5.0,"1",titel ,data, imv1, false)); - } - } - for(int i = 0; i < streamingData.size(); i++){ - streamingRoot.getChildren().add( new TreeItem(streamingData.get(i))); //adds data to root-node - } - } - } - //removes the ending - private String ohneEndung (String str) { - if (str == null) return null; - int pos = str.lastIndexOf("."); - if (pos == -1) return str; - return str.substring(0, pos); - } - - //set color of UI-Elements - void applyColor(){ - String style = "-fx-background-color: #"+getColor()+";"; - String btnStyleBlack = "-fx-button-type: RAISED; -fx-background-color: #"+getColor()+"; -fx-text-fill: BLACK;"; - String btnStyleWhite = "-fx-button-type: RAISED; -fx-background-color: #"+getColor()+"; -fx-text-fill: WHITE;"; - BigInteger icolor = new BigInteger(getColor(),16); - BigInteger ccolor = new BigInteger("78909cff",16); - - sideMenuVBox.setStyle(style); - topHBox.setStyle(style); - tfsearch.setFocusColor(Color.valueOf(getColor())); - tfPath.setFocusColor(Color.valueOf(getColor())); - - if(icolor.compareTo(ccolor) == -1){ - settingsBtn.setStyle("-fx-text-fill: WHITE;"); - streamingSettingsBtn.setStyle("-fx-text-fill: WHITE;"); - switchBtn.setStyle("-fx-text-fill: WHITE;"); - infoBtn.setStyle("-fx-text-fill: WHITE;"); - debugBtn.setStyle("-fx-text-fill: WHITE;"); - directoryBtn.setStyle(btnStyleWhite); - streamingDirectoryBtn.setStyle(btnStyleWhite); - updateBtn.setStyle(btnStyleWhite); - playbtn.setStyle(btnStyleWhite); - openfolderbtn.setStyle(btnStyleWhite); - returnBtn.setStyle(btnStyleWhite); - forwardBtn.setStyle(btnStyleWhite); - playbtn.setGraphic(play_arrow_white); - returnBtn.setGraphic(skip_previous_white); - forwardBtn.setGraphic(skip_next_white); - menuHam.getStyleClass().add("jfx-hamburgerW"); - }else{ - settingsBtn.setStyle("-fx-text-fill: BLACK;"); - streamingSettingsBtn.setStyle("-fx-text-fill: BLACK;"); - switchBtn.setStyle("-fx-text-fill: BLACK;"); - infoBtn.setStyle("-fx-text-fill: BLACK;"); - debugBtn.setStyle("-fx-text-fill: BLACK;"); - directoryBtn.setStyle(btnStyleBlack); - streamingDirectoryBtn.setStyle(btnStyleBlack); - updateBtn.setStyle(btnStyleBlack); - playbtn.setStyle(btnStyleBlack); - openfolderbtn.setStyle(btnStyleBlack); - returnBtn.setStyle(btnStyleBlack); - forwardBtn.setStyle(btnStyleBlack); - playbtn.setGraphic(play_arrow_black); - returnBtn.setGraphic(skip_previous_black); - forwardBtn.setGraphic(skip_next_black); - menuHam.getStyleClass().add("jfx-hamburgerB"); - } - - if(mode.equals("local")){ - switchBtn.setText("streaming"); - }else if(mode.equals("streaming")){ - switchBtn.setText("local"); - } - } - - private void sideMenuSlideIn(){ - sideMenuVBox.setVisible(true); - //fade in from 40% to 100% opacity in 400ms - FadeTransition fadeTransition = new FadeTransition(Duration.millis(400), sideMenuVBox); - fadeTransition.setFromValue(0.4); - fadeTransition.setToValue(1.0); - //slide in in 400ms - TranslateTransition translateTransition = new TranslateTransition(Duration.millis(400), sideMenuVBox); - translateTransition.setFromX(-150); - translateTransition.setToX(0); - //in case both animations are used (add (fadeTransition, translateTransition) in the second line under this command) - ParallelTransition parallelTransition = new ParallelTransition(); - parallelTransition.getChildren().addAll(translateTransition);//(fadeTransition, translateTransition); - parallelTransition.play(); - } - - private void sideMenuSlideOut(){ -// sideMenuVBox.setVisible(false); - //fade out from 100% to 40% opacity in 400ms - FadeTransition fadeTransition = new FadeTransition(Duration.millis(400), sideMenuVBox); - fadeTransition.setFromValue(1.0); - fadeTransition.setToValue(0.4); - //slide out in 400ms - TranslateTransition translateTransition = new TranslateTransition(Duration.millis(400), sideMenuVBox); - translateTransition.setFromX(0); - translateTransition.setToX(-150); - //in case both animations are used (add (fadeTransition, translateTransition) in the second line under this command) - ParallelTransition parallelTransition = new ParallelTransition(); - parallelTransition.getChildren().addAll(translateTransition);//(fadeTransition, translateTransition); - parallelTransition.play(); - } - - void setLocalUI(){ - switch(getLocal()){ - case "en_US": - bundle = ResourceBundle.getBundle("resources.HomeFlix-Local", Locale.US); //us_English - cbLocal.getSelectionModel().select(0); - break; - case "de_DE": - bundle = ResourceBundle.getBundle("resources.HomeFlix-Local", Locale.GERMAN); //German - cbLocal.getSelectionModel().select(1); - break; - default: - bundle = ResourceBundle.getBundle("resources.HomeFlix-Local", Locale.US); //default local - cbLocal.getSelectionModel().select(0); - break; - } - infoBtn.setText(bundle.getString("info")); - settingsBtn.setText(bundle.getString("settings")); - streamingSettingsBtn.setText(bundle.getString("streamingSettings")); - tfPath.setPromptText(bundle.getString("tfPath")); - tfStreamingPath.setPromptText(bundle.getString("tfPath")); - tfsearch.setPromptText(bundle.getString("tfSearch")); - openfolderbtn.setText(bundle.getString("openFolder")); - updateBtn.setText(bundle.getString("checkUpdates")); - directoryBtn.setText(bundle.getString("chooseFolder")); - streamingDirectoryBtn.setText(bundle.getString("chooseFolder")); - settingsHead1Label.setText(bundle.getString("settingsHead1Label")); - mainColorLabel.setText(bundle.getString("mainColorLabel")); - fontsizeLabel.setText(bundle.getString("fontsizeLabel")); - localLabel.setText(bundle.getString("localLabel")); - autoUpdateLabel.setText(bundle.getString("autoUpdateLabel")); - versionLabel.setText(bundle.getString("version")+" "+version+" (Build: "+buildNumber+")"); - columnTitel.setText(bundle.getString("columnName")); - columnRating.setText(bundle.getString("columnRating")); - columnStreamUrl.setText(bundle.getString("columnStreamUrl")); - columnResolution.setText(bundle.getString("columnResolution")); - columnSeason.setText(bundle.getString("columnSeason")); - columnYear.setText(bundle.getString("columnYear")); - errorUpdateD = bundle.getString("errorUpdateD"); - errorUpdateV = bundle.getString("errorUpdateV"); - errorPlay = bundle.getString("errorPlay"); - errorOpenStream = bundle.getString("errorOpenStream"); - errorMode = bundle.getString("errorMode"); - errorLoad = bundle.getString("errorLoad"); - errorSave = bundle.getString("errorSave"); - noFilmFound = bundle.getString("noFilmFound"); - infoText = bundle.getString("version")+" "+version+" (Build: "+buildNumber+") "+versionName+bundle.getString("infoText"); - vlcNotInstalled = bundle.getString("vlcNotInstalled"); - - title = bundle.getString("title"); - year = bundle.getString("year"); - rating = bundle.getString("rating"); - publishedOn = bundle.getString("publishedOn"); - duration = bundle.getString("duration"); - genre = bundle.getString("genre"); - director = bundle.getString("director"); - writer = bundle.getString("writer"); - actors = bundle.getString("actors"); - plot = bundle.getString("plot"); - language = bundle.getString("language"); - country = bundle.getString("country"); - awards = bundle.getString("awards"); - metascore = bundle.getString("metascore"); - imdbRating = bundle.getString("imdbRating"); - type = bundle.getString("type"); - } - - void showErrorMsg(String msg, IOException exception){ - Alert alert = new Alert(AlertType.ERROR); - alert.setTitle("Error"); - alert.setHeaderText(""); - alert.setContentText(msg); - alert.initOwner(main.primaryStage); - - // Create expandable Exception. - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - exception.printStackTrace(pw); - String exceptionText = sw.toString(); - - TextArea textArea = new TextArea(exceptionText); - textArea.setEditable(false); - textArea.setWrapText(true); - - textArea.setMaxWidth(Double.MAX_VALUE); - textArea.setMaxHeight(Double.MAX_VALUE); - GridPane.setVgrow(textArea, Priority.ALWAYS); - GridPane.setHgrow(textArea, Priority.ALWAYS); - - GridPane expContent = new GridPane(); - expContent.setMaxWidth(Double.MAX_VALUE); - expContent.add(textArea, 0, 1); - - // Set expandable Exception into the dialog pane. - alert.getDialogPane().setExpandableContent(expContent); - alert.showAndWait(); - - exception.printStackTrace(); - - } - - //saves the Settings - public void saveSettings(){ - System.out.println("saving settings ..."); - OutputStream outputStream; //new output-stream - try { - props.setProperty("path", getPath()); //writes path into property - props.setProperty("color", getColor()); - props.setProperty("autoUpdate", String.valueOf(isAutoUpdate())); - props.setProperty("size", getSize().toString()); - props.setProperty("local", getLocal()); - props.setProperty("streamingPath", getStreamingPath()); - props.setProperty("mode", getMode()); - props.setProperty("ratingSortType", columnRating.getSortType().toString()); - if(System.getProperty("os.name").equals("Linux")){ - outputStream = new FileOutputStream(fileLinux); - }else{ - outputStream = new FileOutputStream(fileWin); - } - props.storeToXML(outputStream, "Project HomeFlix settings"); //writes new .xml - outputStream.close(); - } catch (IOException e) { - if(firststart == false){ - showErrorMsg(errorLoad, e); - e.printStackTrace(); - } - } - } - - //loads the Settings - public void loadSettings(){ - System.out.println("loading settings ..."); - InputStream inputStream; - try { - if(System.getProperty("os.name").equals("Linux")){ - inputStream = new FileInputStream(fileLinux); - }else{ - inputStream = new FileInputStream(fileWin); - } - props.loadFromXML(inputStream); //new input-stream from .xml - path = props.getProperty("path"); //read path from property - streamingPath = props.getProperty("streamingPath"); - color = props.getProperty("color"); - size = Double.parseDouble(props.getProperty("size")); - autoUpdate = Boolean.parseBoolean(props.getProperty("autoUpdate")); - local = props.getProperty("local"); - ratingSortType = props.getProperty("ratingSortType"); - - switch (props.getProperty("mode")) { - case "local": - mode = "local"; - break; - case "streaming": - mode = "streaming"; - break; - default: - mode = "local"; - break; - } - - inputStream.close(); - } catch (IOException e) { - if(firststart == false){ - showErrorMsg(errorSave, e); - e.printStackTrace(); - } -// showErrorMsg(errorLoad, e); //TODO This should not be visible at first startup - } - } - - //cuts 0x of the Color-pickers return value - private void editColor(String input){ - StringBuilder sb = new StringBuilder(input); - sb.delete(0, 2); - this.color = sb.toString(); - saveSettings(); - } - - //getter and setter - public void setColor(String input){ - this.color = input; - } - - public String getColor(){ - return color; - } - - public void setPath(String input){ - this.path = input; - } - - public String getPath(){ - return path; - } - - public void setStreamingPath(String input){ - this.streamingPath = input; - } - - public String getStreamingPath(){ - return streamingPath; - } - - public void setSize(Double input){ - this.size = input; - } - - public Double getSize(){ - return size; - } - - public void setAutoUpdate(boolean input){ - this.autoUpdate = input; - } - - public boolean isAutoUpdate(){ - return autoUpdate; - } - - public void setLocal(String input){ - this.local = input; - } - - public String getLocal(){ - return local; - } - - public void setMode(String input){ - this.mode = input; - } - - public String getMode(){ - return mode; - } - - public String getCurrentWorkingDirectory() { - return currentWorkingDirectory; - } - - public void setCurrentWorkingDirectory(String currentWorkingDirectory) { - this.currentWorkingDirectory = currentWorkingDirectory; - } -} diff --git a/src/application/apiQuery.java b/src/application/apiQuery.java deleted file mode 100644 index 545ca89..0000000 --- a/src/application/apiQuery.java +++ /dev/null @@ -1,211 +0,0 @@ -/** - * apiQuery for Project HomeFlix - * sends a query to the omdb api - */ -package application; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.BufferedReader; -import java.io.File; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.Scanner; - -import javax.imageio.ImageIO; - -import com.eclipsesource.json.Json; -import com.eclipsesource.json.JsonObject; - -import javafx.scene.image.Image; -import javafx.scene.text.Font; -import javafx.scene.text.FontWeight; -import javafx.scene.text.Text; - -public class apiQuery{ - - public apiQuery(MainWindowController m, DBController db, Main main){ - mainWindowController=m; - dbController=db; - this.main = main; - } - - private MainWindowController mainWindowController; - private DBController dbController; - private Main main; - private Image im; - private String[] responseString = new String[20]; - private String posterCache; - private String apiURL = "https://www.omdbapi.com/?apikey="; - private String apiKey = "b9f9fd23"; - ArrayList responseText = new ArrayList(); - ArrayList nameText = new ArrayList(); - - void startQuery(String titel, String streamUrl){ - URL queryURL = null; - Scanner sc = null; - String moviename = null; - String retdata = null; - String posterPath = null; - InputStream is = null; - BufferedReader br = null; - String fontFamily = main.getFONT_FAMILY(); - posterCache = main.getPosterCache().toString(); - int fontSize = (int) Math.round(mainWindowController.size); - - responseText.removeAll(responseText); - nameText.removeAll(nameText); - - try { - - //get film title - sc = new Scanner(System.in); - moviename = titel; - - // in case of no or "" Film title - if (moviename == null || moviename.equals("")) { - System.out.println("No movie found"); - } - - //remove unwanted blank - moviename = moviename.trim(); - - //replace blank with + - moviename = moviename.replace(" ", "+"); - - //queryURL is apiURL and additional parameters, response-types: http,json,xml (must be json, since the response is processed with minimal-json ) - queryURL = new URL(apiURL + apiKey + "&t=" + moviename + "&plot=full&r=json"); - is = queryURL.openStream(); - br = new BufferedReader(new InputStreamReader(is, "UTF-8")); - - //read data from response Stream - while ((retdata = br.readLine()) != null) { - //cut the json response into separate strings - System.out.println(retdata); - JsonObject object = Json.parse(retdata).asObject(); - - responseString[0] = object.getString("Title", ""); - responseString[1] = object.getString("Year", ""); - responseString[2] = object.getString("Rated", ""); - responseString[3] = object.getString("Released", ""); - responseString[4] = object.getString("Runtime", ""); - responseString[5] = object.getString("Genre", ""); - responseString[6] = object.getString("Director", ""); - responseString[7] = object.getString("Writer", ""); - responseString[8] = object.getString("Actors", ""); - responseString[9] = object.getString("Plot", ""); - responseString[10] = object.getString("Language", ""); - responseString[11] = object.getString("Country", ""); - responseString[12] = object.getString("Awards", ""); - responseString[13] = object.getString("Metascore", ""); - responseString[14] = object.getString("imdbRating", ""); - responseString[15] = object.getString("Type", ""); - responseString[16] = object.getString("imdbVotes", ""); - responseString[17] = object.getString("imdbID", ""); - responseString[18] = object.getString("Poster", ""); - responseString[19] = object.getString("Response", ""); - - //adding poster to cache - BufferedImage originalImage = ImageIO.read(new URL(responseString[18]));//change path to where file is located - int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType(); - BufferedImage resizeImagePNG = resizeImage(originalImage, type, 198, 297); - if(System.getProperty("os.name").equals("Linux")) { - posterPath = posterCache+"/"+titel+".png"; - ImageIO.write(resizeImagePNG, "png", new File(posterCache+"/"+titel+".png")); //change path where you want it saved - } else { - ImageIO.write(resizeImagePNG, "png", new File(posterCache+"\\"+titel+".png")); //change path where you want it saved - posterPath = posterCache+"\\"+titel+".png"; - } - System.out.println("adding poster to cache: "+posterPath); - - //adding strings to the cache - dbController.addCache( streamUrl, responseString[0], responseString[1],responseString[2], responseString[3], responseString[4], responseString[5], - responseString[6], responseString[7], responseString[8], responseString[9], responseString[10],responseString[11], responseString[12], - responseString[13], responseString[14], responseString[15], responseString[16], responseString[17], posterPath, - responseString[19]); - dbController.setCached(streamUrl); - - for(int i=0; i<20; i++){ - Text text = new Text(responseString[i]+"\n"); - responseText.add(text); - responseText.get(i).setFont(Font.font(fontFamily, fontSize)); - } - - //if response == false then show mainWindowController.noFilmFound else create new Texts and add them to flowText - if(retdata.contains("\"Response\":\"False\"")){ //TODO + FIXME - mainWindowController.textFlow.getChildren().add(new Text(mainWindowController.noFilmFound)); - im = new Image("resources/icons/close_black_2048x2048.png"); - mainWindowController.image1.setImage(im); - }else{ - nameText.add(0, new Text(mainWindowController.title+": ")); - nameText.add(1, new Text(mainWindowController.year+": ")); - nameText.add(2, new Text(mainWindowController.rating+": ")); - nameText.add(3, new Text(mainWindowController.publishedOn+": ")); - nameText.add(4, new Text(mainWindowController.duration+": ")); - nameText.add(5, new Text(mainWindowController.genre+": ")); - nameText.add(6, new Text(mainWindowController.director+": ")); - nameText.add(7, new Text(mainWindowController.writer+": ")); - nameText.add(8, new Text(mainWindowController.actors+": ")); - nameText.add(9, new Text(mainWindowController.plot+": ")); - nameText.add(10, new Text(mainWindowController.language+": ")); - nameText.add(11, new Text(mainWindowController.country+": ")); - nameText.add(12, new Text(mainWindowController.awards+": ")); - nameText.add(13, new Text(mainWindowController.metascore+": ")); - nameText.add(14, new Text(mainWindowController.imdbRating+": ")); - nameText.add(15, new Text(mainWindowController.type+": ")); - - for(int i=0; i image = new SimpleObjectProperty<>(); - private final BooleanProperty cached = new SimpleBooleanProperty(); - - /** - * tableData is the data-type of tree-table-view - * @param year: the release year of the film - * @param season: season if it's a series - * @param episode: episode if it's a series - * @param rating: indicator for favourites, used for sorting the items - * @param resolution: resolution of the film - * @param titel: title of the film - * @param streamUrl: the concrete path to the file or the URL - * @param image: the favourite icon - * @param cached: indicator for caching status - */ - public tableData (final int year, final int season, final int episode, final double rating, final String resolution, final String title, final String streamUrl, final ImageView image, final boolean cached) { - this.year.set(year); - this.season.set(season); - this.episode.set(episode); - this.rating.set(rating); - this.resolution.set(resolution); - this.title.set(title); - this.streamUrl.set(streamUrl); - this.image.set(image); - this.cached.set(cached); - } - - public IntegerProperty yearProperty(){ - return year; - } - - public IntegerProperty seasonProperty(){ - return season; - } - - public IntegerProperty episodeProperty(){ - return episode; - } - - public DoubleProperty ratingProperty(){ - return rating; - } - - public StringProperty resolutionProperty(){ - return resolution; - } - - public StringProperty titleProperty(){ - return title; - } - - public StringProperty streamUrlProperty(){ - return streamUrl; - } - - public SimpleObjectProperty imageProperty(){ - return image; - } - - public BooleanProperty cachedProperty(){ - return cached; - } - - - public final int getYear() { - return yearProperty().get(); - } - - public final int getSeason() { - return seasonProperty().get(); - } - - public final int getEpisode() { - return episodeProperty().get(); - } - - public final double getRating() { - return ratingProperty().get(); - } - - public final String getResolution() { - return resolutionProperty().get(); - } - - public final String getTitle() { - return titleProperty().get(); - } - - public final String getStreamUrl() { - return streamUrlProperty().get(); - } - - public final ImageView getImage() { - return imageProperty().get(); - } - - public final boolean getCached(){ - return cachedProperty().get(); - } - - - public final void setYear(int year) { - yearProperty().set(year); - } - - public final void setSeason(int season) { - seasonProperty().set(season); - } - - public final void setEpisode(int season) { - episodeProperty().set(season); - } - - public final void setRating(int rating) { - ratingProperty().set(rating); - } - - public final void setResolution(String resolution) { - resolutionProperty().set(resolution); - } - - public final void setTitle(String title) { - titleProperty().set(title); - } - - public final void setStreamUrl(String streamUrl) { - streamUrlProperty().set(streamUrl); - } - - public final void setImage(ImageView image) { - imageProperty().set(image); - } - - public final void setCached(boolean cached){ - cachedProperty().set(cached); - } -} diff --git a/src/application/updater.java b/src/application/updater.java deleted file mode 100644 index 755a2a6..0000000 --- a/src/application/updater.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * updater for Project HomeFlix - * checks for Updates and downloads it in case there is one - */ -package application; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import javax.swing.ProgressMonitor; -import javax.swing.ProgressMonitorInputStream; - -import org.apache.commons.io.FileUtils; - -import com.eclipsesource.json.Json; -import com.eclipsesource.json.JsonArray; -import com.eclipsesource.json.JsonObject; -import com.eclipsesource.json.JsonValue; - -import javafx.application.Platform; - -public class updater implements Runnable{ - - private MainWindowController mainWindowController; - private String buildNumber; - private String apiOutput; - private String updateBuildNumber; //tag_name from Github - private String browserDownloadUrl; //update download link - private String githubApi = "https://api.github.com/repos/Seil0/Project-HomeFlix/releases/latest"; - - - public updater(MainWindowController m, String buildNumber){ - mainWindowController=m; - this.buildNumber=buildNumber; - } - - public void run(){ - System.out.println("check for updates ..."); - Platform.runLater(() -> { - mainWindowController.updateBtn.setText(mainWindowController.bundle.getString("checkingUpdates")); - }); - - try { - URL githubApiUrl = new URL(githubApi); - BufferedReader ina = new BufferedReader(new InputStreamReader(githubApiUrl.openStream())); - apiOutput = ina.readLine(); - ina.close(); - } catch (IOException e1) { - Platform.runLater(() -> { - mainWindowController.showErrorMsg(mainWindowController.errorUpdateV, e1); - }); - } - - JsonObject object = Json.parse(apiOutput).asObject(); - 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", ""); - - } - System.out.println("Build: "+buildNumber+", Update: "+updateBuildNumber); - - //Compares the program BuildNumber with the current BuildNumber if program BuildNumber < current BuildNumber then perform a update - int iversion = Integer.parseInt(buildNumber); - int iaktVersion = Integer.parseInt(updateBuildNumber.replace(".", "")); - - if(iversion >= iaktVersion){ - Platform.runLater(() -> { - mainWindowController.updateBtn.setText(mainWindowController.bundle.getString("updateBtnNotavail")); - }); - System.out.println("no update available"); - }else{ - Platform.runLater(() -> { - mainWindowController.updateBtn.setText(mainWindowController.bundle.getString("updateBtnavail")); - }); - System.out.println("update available"); - System.out.println("download link: " + browserDownloadUrl); - try { - //open new Http connection, ProgressMonitorInputStream for downloading the data - HttpURLConnection conn = (HttpURLConnection) new URL(browserDownloadUrl).openConnection(); - ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(null, "Downloading...", conn.getInputStream()); - ProgressMonitor pm = pmis.getProgressMonitor(); - pm.setMillisToDecideToPopup(0); - pm.setMillisToPopup(0); - pm.setMinimum(0);// tell the progress bar that we start at the beginning of the stream - pm.setMaximum(conn.getContentLength());// tell the progress bar the total number of bytes we are going to read. - FileUtils.copyInputStreamToFile(pmis, new File("ProjectHomeFlix_update.jar")); //download update - org.apache.commons.io.FileUtils.copyFile(new File("ProjectHomeFlix_update.jar"), new File("ProjectHomeFlix.jar")); //TODO rename update to old name - org.apache.commons.io.FileUtils.deleteQuietly(new File("ProjectHomeFlix_update.jar")); //delete update - Runtime.getRuntime().exec("java -jar ProjectHomeFlix.jar"); //start again - System.exit(0); //finishes itself - } catch (IOException e) { - Platform.runLater(() -> { - mainWindowController.showErrorMsg(mainWindowController.errorUpdateD, e); - }); - } - } - } -} diff --git a/src/libraries/Licenses/Apache_License.txt b/src/libraries/Licenses/Apache_License.txt deleted file mode 100644 index d645695..0000000 --- a/src/libraries/Licenses/Apache_License.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/libraries/Licenses/MIT_License.txt b/src/libraries/Licenses/MIT_License.txt deleted file mode 100644 index 5e83ac1..0000000 --- a/src/libraries/Licenses/MIT_License.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013, 2014 EclipseSource - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/src/libraries/commons-io-2.5.jar b/src/libraries/commons-io-2.5.jar deleted file mode 100644 index 107b061..0000000 Binary files a/src/libraries/commons-io-2.5.jar and /dev/null differ diff --git a/src/libraries/jfoenix-1.4.0.jar b/src/libraries/jfoenix-1.4.0.jar deleted file mode 100644 index 789ef3b..0000000 Binary files a/src/libraries/jfoenix-1.4.0.jar and /dev/null differ diff --git a/src/libraries/minimal-json-0.9.4.jar b/src/libraries/minimal-json-0.9.4.jar deleted file mode 100644 index 14c0633..0000000 Binary files a/src/libraries/minimal-json-0.9.4.jar and /dev/null differ diff --git a/src/libraries/sqlite-jdbc-3.18.0.jar b/src/libraries/sqlite-jdbc-3.18.0.jar deleted file mode 100644 index 8e9dce1..0000000 Binary files a/src/libraries/sqlite-jdbc-3.18.0.jar and /dev/null differ diff --git a/src/main/java/com/cemu_UI/uiElements/JFXInfoDialog.java b/src/main/java/com/cemu_UI/uiElements/JFXInfoDialog.java new file mode 100644 index 0000000..9c2b710 --- /dev/null +++ b/src/main/java/com/cemu_UI/uiElements/JFXInfoDialog.java @@ -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() { + @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(); + } +} diff --git a/src/main/java/com/cemu_UI/uiElements/JFXOkayCancelDialog.java b/src/main/java/com/cemu_UI/uiElements/JFXOkayCancelDialog.java new file mode 100644 index 0000000..5dd4d1a --- /dev/null +++ b/src/main/java/com/cemu_UI/uiElements/JFXOkayCancelDialog.java @@ -0,0 +1,142 @@ +/** + * 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.util.ResourceBundle; + +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 JFXOkayCancelDialog { + + private String headingText; + private String bodyText; + private String dialogBtnStyle; + private String okayText; + private String cancelText; + private int dialogWidth; + private int dialogHeight; + private EventHandler okayAction; + private EventHandler cancelAction; + private Pane pane; + + /** + * 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 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 JFXOkayCancelDialog(String headingText, String bodyText, String dialogBtnStyle, int dialogWidth, + int dialogHeight, EventHandler okayAction, EventHandler cancelAction, Pane pane, + ResourceBundle bundle) { + this.headingText = headingText; + this.bodyText = bodyText; + this.dialogBtnStyle = dialogBtnStyle; + this.dialogWidth = dialogWidth; + this.dialogHeight = dialogHeight; + this.okayAction = okayAction; + this.cancelAction = cancelAction; + this.pane = pane; + okayText = bundle.getString("okayBtnText"); + cancelText = bundle.getString("cancelBtnText"); + } + + public void show() { + + 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); + okayBtn.addEventHandler(ActionEvent.ACTION, (e)-> { + dialog.close(); + }); + okayBtn.addEventHandler(ActionEvent.ACTION, okayAction); + okayBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED); + okayBtn.setPrefHeight(32); + okayBtn.setStyle(dialogBtnStyle); + JFXButton cancelBtn = new JFXButton(cancelText); + cancelBtn.addEventHandler(ActionEvent.ACTION, (e)-> { + dialog.close(); + }); + cancelBtn.addEventHandler(ActionEvent.ACTION, cancelAction); + cancelBtn.setButtonType(com.jfoenix.controls.JFXButton.ButtonType.RAISED); + cancelBtn.setPrefHeight(32); + cancelBtn.setStyle(dialogBtnStyle); + content.setActions(cancelBtn, 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 String getOkayText() { + return okayText; + } + + public void setOkayText(String okayText) { + this.okayText = okayText; + } + + public String getCancelText() { + return cancelText; + } + + public void setCancelText(String cancelText) { + this.cancelText = cancelText; + } + + public EventHandler getOkayAction() { + return okayAction; + } + + public void setOkayAction(EventHandler okayAction) { + this.okayAction = okayAction; + } + + public EventHandler getCancelAction() { + return cancelAction; + } + + public void setCancelAction(EventHandler cancelAction) { + this.cancelAction = cancelAction; + } + +} + diff --git a/src/main/java/com/cemu_UI/uiElements/JFXTextAreaInfoDialog.java b/src/main/java/com/cemu_UI/uiElements/JFXTextAreaInfoDialog.java new file mode 100644 index 0000000..fd8ff2f --- /dev/null +++ b/src/main/java/com/cemu_UI/uiElements/JFXTextAreaInfoDialog.java @@ -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() { + @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; + } +} diff --git a/src/main/java/kellerkinder/HomeFlix/application/Main.java b/src/main/java/kellerkinder/HomeFlix/application/Main.java new file mode 100644 index 0000000..9d211f6 --- /dev/null +++ b/src/main/java/kellerkinder/HomeFlix/application/Main.java @@ -0,0 +1,218 @@ +/** + * Project-HomeFlix + * + * Copyright 2016-2018 <@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 kellerkinder.HomeFlix.application; + +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.Optional; +import java.util.ResourceBundle; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonType; +import javafx.scene.image.Image; +import javafx.scene.layout.AnchorPane; +import javafx.stage.DirectoryChooser; +import javafx.stage.Stage; + +public class Main extends Application { + + private Stage primaryStage; + private Scene scene; + private AnchorPane pane; + private MainWindowController mainWindowController; + private static String userHome = System.getProperty("user.home"); + private static String userName = System.getProperty("user.name"); + 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 dirWin = userHome + "/Documents/HomeFlix"; //Windows: C:/Users/"User"/Documents/HomeFlix + private String dirLinux = userHome + "/HomeFlix"; //Linux: /home/"User"/HomeFlix + private File directory; + private File configFile; + private File posterCache; + + private String path; + private String FONT_FAMILY = "System"; + private String local = System.getProperty("user.language")+"_"+System.getProperty("user.country"); + private double FONT_SIZE = 17; + private ResourceBundle bundle; + private static Logger LOGGER; + + @Override + public void start(Stage primaryStage) throws IOException { + LOGGER.info("OS: " + osName + " " + osVers + " " + osArch); + LOGGER.info("Java: " + javaVend + " " + javaVers); + LOGGER.info("User: " + userName + " " + userHome); + + this.primaryStage = primaryStage; + mainWindow(); + } + + private void mainWindow(){ + try { + FXMLLoader loader = new FXMLLoader(); + loader.setLocation(ClassLoader.getSystemResource("fxml/MainWindow.fxml")); + pane = (AnchorPane) loader.load(); + primaryStage.setMinHeight(600.00); + primaryStage.setMinWidth(1000.00); + primaryStage.setResizable(false); + primaryStage.setTitle("Project HomeFlix"); + primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/icons/Homeflix_Icon_64x64.png"))); //adds application icon + mainWindowController = loader.getController(); //Link of FXMLController and controller class + mainWindowController.setMain(this); //call setMain + + + // get OS and the specific paths + if (osName.equals("Windows")) { + directory = new File(dirWin); + configFile = new File(dirWin + "/config.xml"); + posterCache = new File(dirWin + "/posterCache"); + } else { + directory = new File(dirLinux); + configFile = new File(dirLinux + "/config.xml"); + posterCache = new File(dirLinux + "/posterCache"); + } + + // startup checks + if (!configFile.exists()) { + directory.mkdir(); + mainWindowController.addSource(firstStart(), "local"); + mainWindowController.setColor("ee3523"); + mainWindowController.setSize(FONT_SIZE); + mainWindowController.setAutoUpdate(false); + mainWindowController.setLocal(local); + mainWindowController.saveSettings(); + try { + Runtime.getRuntime().exec("java -jar ProjectHomeFlix.jar"); // start again (preventing Bugs) TODO is this really needed + System.exit(0); // finishes it self + } catch (Exception e) { + LOGGER.error("error while restarting HomeFlix", e); + } + } + + if (!posterCache.exists()) { + posterCache.mkdir(); + } + + // generate window + scene = new Scene(pane); // create new scene, append pane to scene + scene.getStylesheets().add(getClass().getResource("/css/MainWindow.css").toExternalForm()); + primaryStage.setScene(scene); // append scene to stage + primaryStage.show(); // show stage + + // init here as it loads the games to the mwc and the gui, therefore the window must exist + mainWindowController.init(); + mainWindowController.getDbController().init(); + } catch (IOException e) { + LOGGER.error(e); + } + } + + // Method for first Start + private String firstStart(){ + switch (System.getProperty("user.language") + "_" + System.getProperty("user.country")) { + case "en_US": + bundle = ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.US); // us_english + break; + case "de_DE": + bundle = ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.GERMAN); // German + break; + default: + bundle = ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.US); // default local + break; + } + + Alert alert = new Alert(AlertType.CONFIRMATION); //new alert with file-chooser + alert.setTitle("Project HomeFlix"); + alert.setHeaderText(bundle.getString("firstStartHeader")); + alert.setContentText(bundle.getString("firstStartContent")); + + Optional result = alert.showAndWait(); + if (result.get() == ButtonType.OK){ + DirectoryChooser directoryChooser = new DirectoryChooser(); + File selectedDirectory = + directoryChooser.showDialog(primaryStage); + path = selectedDirectory.getAbsolutePath(); + + } else { + path = ""; + } + return path; + } + + public static void main(String[] args) { + if(System.getProperty("os.name").equals("Windows")){ + System.setProperty("logFilename", userHome + "/Documents/HomeFlix/app.log"); + File logFile = new File(userHome + "/Documents/HomeFlix/app.log"); + logFile.delete(); + }else{ + System.setProperty("logFilename", userHome + "/HomeFlix/app.log"); + File logFile = new File(userHome + "/HomeFlix/app.log"); + logFile.delete(); + } + LOGGER = LogManager.getLogger(Main.class.getName()); + launch(args); + } + + public Stage getPrimaryStage() { + return primaryStage; + } + + public void setPrimaryStage(Stage primaryStage) { + this.primaryStage = primaryStage; + } + + public AnchorPane getPane( ) { + return pane; + } + + public String getFONT_FAMILY() { + return FONT_FAMILY; + } + + public void setFONT_FAMILY(String FONT_FAMILY) { + this.FONT_FAMILY = FONT_FAMILY; + } + + public File getDirectory() { + return directory; + } + + public File getConfigFile() { + return configFile; + } + + public File getPosterCache() { + return posterCache; + } +} \ No newline at end of file diff --git a/src/main/java/kellerkinder/HomeFlix/application/MainWindowController.java b/src/main/java/kellerkinder/HomeFlix/application/MainWindowController.java new file mode 100644 index 0000000..918c9e6 --- /dev/null +++ b/src/main/java/kellerkinder/HomeFlix/application/MainWindowController.java @@ -0,0 +1,1104 @@ +/** + * Project-HomeFlix + * + * Copyright 2016-2018 <@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 kellerkinder.HomeFlix.application; + +import java.awt.Desktop; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.math.BigInteger; +import java.util.ArrayList; +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.uiElements.JFXInfoDialog; +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXColorPicker; +import com.jfoenix.controls.JFXHamburger; +import com.jfoenix.controls.JFXSlider; +import com.jfoenix.controls.JFXTextField; +import com.jfoenix.controls.JFXToggleButton; +import com.jfoenix.transitions.hamburger.HamburgerBackArrowBasicTransition; + +import javafx.animation.TranslateTransition; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ChoiceBox; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.Label; +import javafx.scene.control.MenuItem; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.TextArea; +import javafx.scene.control.TreeItem; +import javafx.scene.control.TreeTableColumn; +import javafx.scene.control.TreeTableColumn.SortType; +import javafx.scene.control.TreeTableView; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.scene.text.TextFlow; +import javafx.stage.DirectoryChooser; +import javafx.stage.FileChooser; +import javafx.util.Duration; +import kellerkinder.HomeFlix.controller.DBController; +import kellerkinder.HomeFlix.controller.OMDbAPIController; +import kellerkinder.HomeFlix.controller.UpdateController; +import kellerkinder.HomeFlix.datatypes.SourceDataType; +import kellerkinder.HomeFlix.datatypes.FilmTabelDataType; + +public class MainWindowController { + + @FXML + private AnchorPane mainAnchorPane; + + @FXML + private ScrollPane settingsScrollPane; + + @FXML + private ScrollPane textScrollPane; + + @FXML + private HBox topHBox; + + @FXML + private VBox sideMenuVBox; + + @FXML + private TreeTableView filmsTreeTable; + + @FXML + private TableView sourcesTable; + + @FXML + private TextFlow textFlow; + + @FXML + private JFXButton playbtn; + + @FXML + private JFXButton openfolderbtn; + + @FXML + private JFXButton returnBtn; + + @FXML + private JFXButton forwardBtn; + + @FXML + private JFXButton aboutBtn; + + @FXML + private JFXButton settingsBtn; + + @FXML + private JFXButton debugBtn; + + @FXML + public JFXButton updateBtn; + + @FXML + private JFXButton addDirectoryBtn; + + @FXML + private JFXButton addStreamSourceBtn; + + @FXML + private JFXHamburger menuHam; + + @FXML + private JFXToggleButton autoUpdateToggleBtn; + + @FXML + private JFXTextField searchTextField; + + @FXML + public JFXColorPicker colorPicker; + + @FXML + public ChoiceBox languageChoisBox = new ChoiceBox<>(); + + @FXML + public ChoiceBox branchChoisBox = new ChoiceBox<>(); + + @FXML + public JFXSlider fontsizeSlider; + + @FXML + private Label homeflixSettingsLbl; + + @FXML + private Label mainColorLbl; + + @FXML + private Label fontsizeLbl; + + @FXML + private Label languageLbl; + + @FXML + private Label updateLbl; + + @FXML + private Label branchLbl; + + @FXML + private Label sourcesLbl; + + @FXML + private Label versionLbl; + + @FXML + private ImageView posterImageView; + private ImageView imv1; + + @FXML + private TreeItem filmRoot = new TreeItem<>(new FilmTabelDataType("", "", "", "", false, false, imv1)); + @FXML + private TreeTableColumn columnStreamUrl = new TreeTableColumn<>("File Name"); + @FXML + private TreeTableColumn columnTitle = new TreeTableColumn<>("Title"); + @FXML + private TreeTableColumn columnSeason = new TreeTableColumn<>("Season"); + @FXML + private TreeTableColumn columnEpisode = new TreeTableColumn<>("Episode"); + @FXML + private TreeTableColumn columnFavorite = new TreeTableColumn<>("Favorite"); + + @FXML + private TreeItem sourceRoot =new TreeItem<>(new SourceDataType("", "")); + @FXML + private TableColumn sourceColumn; + @FXML + private TableColumn modeColumn; + + private boolean menuTrue = false; + private boolean settingsTrue = false; + private boolean autoUpdate = false; + private boolean useBeta = false; + private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName()); + private int hashA = -647380320; + + private String version = "0.6.0"; + private String buildNumber = "141"; + private String versionName = "plasma vampire"; + private String dialogBtnStyle; + private String color; + private String title; + private String streamUrl; + private String ratingSortType; + private String local; + private String omdbAPIKey; + + // text strings + private String errorPlay; + private String errorLoad; + private String errorSave; + private String infoText; + private String vlcNotInstalled; + + public double size; + private int last; + private int indexTable; + private int indexList; + private int next; + private ResourceBundle bundle; + + private ObservableList languages = FXCollections.observableArrayList("English (en_US)", "Deutsch (de_DE)"); + private ObservableList branches = FXCollections.observableArrayList("stable", "beta"); + private ObservableList filterData = FXCollections.observableArrayList(); + private ObservableList filmsList = FXCollections.observableArrayList(); + private ObservableList sourcesList = FXCollections.observableArrayList(); + private ImageView skip_previous_white = new ImageView(new Image("icons/ic_skip_previous_white_18dp_1x.png")); + private ImageView skip_previous_black = new ImageView(new Image("icons/ic_skip_previous_black_18dp_1x.png")); + private ImageView skip_next_white = new ImageView(new Image("icons/ic_skip_next_white_18dp_1x.png")); + private ImageView skip_next_black = new ImageView(new Image("icons/ic_skip_next_black_18dp_1x.png")); + private ImageView play_arrow_white = new ImageView(new Image("icons/ic_play_arrow_white_18dp_1x.png")); + private ImageView play_arrow_black = new ImageView(new Image("icons/ic_play_arrow_black_18dp_1x.png")); + private DirectoryChooser directoryChooser = new DirectoryChooser(); + private MenuItem like = new MenuItem("like"); + private MenuItem dislike = new MenuItem("dislike"); //TODO one option (like or dislike) + private ContextMenu menu = new ContextMenu(like, dislike); + private Properties props = new Properties(); + + private Main main; + private MainWindowController mainWindowController; + private UpdateController updateController; + private OMDbAPIController omdbAPIController; + private DBController dbController; + + /** + * "Main" Method called in Main.java main() when starting + * Initialize other objects: Updater, dbController and ApiQuery + */ + void setMain(Main main) { + this.main = main; + mainWindowController = this; + dbController = new DBController(this.main, this); + omdbAPIController = new OMDbAPIController(this, dbController, this.main); + } + + void init() { + loadSettings(); + checkAutoUpdate(); + initTabel(); + initActions(); + initUI(); + } + + // Initialize the tables (treeTableViewfilm and sourcesTable) + private void initTabel() { + + // film Table + columnStreamUrl.setMaxWidth(0); + columnTitle.setMaxWidth(190); + columnFavorite.setMaxWidth(80); + columnSeason.setMaxWidth(73); + columnEpisode.setMaxWidth(77); + columnFavorite.setStyle("-fx-alignment: CENTER;"); + + filmsTreeTable.setRoot(filmRoot); + filmsTreeTable.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY); + filmsTreeTable.setShowRoot(false); + + // write content into cell + columnStreamUrl.setCellValueFactory(cellData -> cellData.getValue().getValue().streamUrlProperty()); + columnTitle.setCellValueFactory(cellData -> cellData.getValue().getValue().titleProperty()); + columnSeason.setCellValueFactory(cellData -> cellData.getValue().getValue().seasonProperty()); + columnEpisode.setCellValueFactory(cellData -> cellData.getValue().getValue().episodeProperty()); + columnFavorite.setCellValueFactory(cellData -> cellData.getValue().getValue().imageProperty()); + + // add columns to treeTableViewfilm + filmsTreeTable.getColumns().add(columnStreamUrl); + filmsTreeTable.getColumns().add(columnTitle); + filmsTreeTable.getColumns().add(columnFavorite); + filmsTreeTable.getColumns().add(columnSeason); + filmsTreeTable.getColumns().add(columnEpisode); + filmsTreeTable.getColumns().get(0).setVisible(false); //hide columnStreamUrl (important) + + // context menu for treeTableViewfilm + filmsTreeTable.setContextMenu(menu); + + // sourcesTreeTable + sourceColumn.setCellValueFactory(cellData -> cellData.getValue().pathProperty()); + modeColumn.setCellValueFactory(cellData -> cellData.getValue().modeProperty()); + sourcesTable.setItems(sourcesList); + } + + //Initializing the actions + private void initActions() { + + HamburgerBackArrowBasicTransition burgerTask = new HamburgerBackArrowBasicTransition(menuHam); + menuHam.addEventHandler(MouseEvent.MOUSE_PRESSED, (e) -> { + if (menuTrue == false) { + sideMenuSlideIn(); + burgerTask.setRate(1.0); + burgerTask.play(); + menuTrue = true; + } else { + sideMenuSlideOut(); + burgerTask.setRate(-1.0); + burgerTask.play(); + menuTrue = false; + } + if (settingsTrue == true) { + settingsScrollPane.setVisible(false); + saveSettings(); + settingsTrue = false; + } + }); + + searchTextField.textProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, String oldValue, String newValue) { + ObservableList helpData; + filterData.removeAll(filterData); + filmRoot.getChildren().removeAll(filmRoot.getChildren()); + + helpData = filmsList; + + + for (int i = 0; i < helpData.size(); i++) { + if (helpData.get(i).getTitle().toLowerCase().contains(searchTextField.getText().toLowerCase())) { + filterData.add(helpData.get(i)); // add data from newDaten to filteredData where title contains search input + } + } + + for (int i = 0; i < filterData.size(); i++) { + filmRoot.getChildren().add(new TreeItem(filterData.get(i))); // add filtered data to root node after search + } + if (searchTextField.getText().hashCode() == hashA) { + setColor("000000"); + applyColor(); + } + } + }); + + languageChoisBox.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue ov, Number value, Number new_value) { + String local = languageChoisBox.getItems().get((int) new_value).toString(); + local = local.substring(local.length() - 6, local.length() - 1); // reading only en_US from English (en_US) + setLocal(local); + setLocalUI(); + saveSettings(); + } + }); + + branchChoisBox.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue ov, Number value, Number new_value) { + if (branchChoisBox.getItems().get((int) new_value).toString() == "beta") { + setUseBeta(true); + } else { + setUseBeta(false); + } + saveSettings(); + } + }); + + fontsizeSlider.valueProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue ov, Number old_val, Number new_val) { + setSize(fontsizeSlider.getValue()); + if (title != null) { + dbController.readCache(streamUrl); + } + // ta1.setFont(Font.font("System", size)); + saveSettings(); + } + }); + + like.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + dbController.like(streamUrl); + dbController.refresh(streamUrl, indexList); + refreshTable(); + } + }); + + dislike.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + dbController.dislike(streamUrl); + dbController.refresh(streamUrl, indexList); + refreshTable(); + } + }); + + /** + * FIXME fix bug when sort by ASCENDING, wrong order + * FIXME when sorting, series are expanded + */ + columnFavorite.sortTypeProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue paramObservableValue, SortType paramT1, SortType paramT2) { + LOGGER.info("NAME Clicked -- sortType = " + paramT1 + ", SortType=" + paramT2); + ArrayList fav_true = new ArrayList(); + ArrayList fav_false = new ArrayList(); + ObservableList helpData; + filterData.removeAll(filterData); +// treeTableViewfilm.getSelectionModel().clearSelection(selected); + filmRoot.getChildren().removeAll(filmRoot.getChildren()); + + helpData = filmsList; + + for (int i = 0; i < helpData.size(); i++) { + if (helpData.get(i).getFavorite() == true) { + fav_true.add(i); + } else { + fav_false.add(i); + } + } + if (paramT2.toString().equals("DESCENDING")) { + LOGGER.info("Absteigend"); // Debug, delete? + for (int i = 0; i < fav_true.size(); i++) { + filterData.add(helpData.get(fav_true.get(i))); + } + for (int i = 0; i < fav_false.size(); i++) { + filterData.add(helpData.get(fav_false.get(i))); + } + } else { + for (int i = 0; i < fav_false.size(); i++) { + filterData.add(helpData.get(fav_false.get(i))); + } + for (int i = 0; i < fav_true.size(); i++) { + filterData.add(helpData.get(fav_true.get(i))); + } + } + + LOGGER.info(filterData.size()); // Debug, delete? + for (int i = 0; i < filterData.size(); i++) { +// LOGGER.info(filterData.get(i).getTitle()+"; "+filterData.get(i).getRating()); // Debugging + // add filtered data to root node after search + filmRoot.getChildren().add(new TreeItem(filterData.get(i))); + } + } + }); + + // Change-listener for treeTableViewfilm + filmsTreeTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Object oldVal, Object newVal) { + indexTable = filmsTreeTable.getSelectionModel().getSelectedIndex(); // get selected item + last = indexTable - 1; + next = indexTable + 1; + title = columnTitle.getCellData(indexTable); // get name of selected item + streamUrl = columnStreamUrl.getCellData(indexTable); // get file path of selected item + + for (FilmTabelDataType helpData : filmsList) { + if (helpData.getStreamUrl().equals(streamUrl)) { + indexList = filmsList.indexOf(helpData); + } + } + + if (filmsList.get(indexList).getCached()) { + LOGGER.info("loading from cache: " + title); + dbController.readCache(streamUrl); + } else { + omdbAPIController = new OMDbAPIController(mainWindowController, dbController, main); + Thread omdbAPIThread = new Thread(omdbAPIController); + omdbAPIThread.setName("OMDbAPI"); + omdbAPIThread.start(); + } + } + }); + } + + // initialize UI elements + private void initUI() { + debugBtn.setDisable(true); // debugging button for tests + debugBtn.setVisible(false); + + versionLbl.setText("Version: " + version + " (Build: " + buildNumber + ")"); + fontsizeSlider.setValue(getSize()); + colorPicker.setValue(Color.valueOf(getColor())); + + updateBtn.setFont(Font.font("System", 12)); + autoUpdateToggleBtn.setSelected(isAutoUpdate()); + languageChoisBox.setItems(languages); + branchChoisBox.setItems(branches); + + if (isUseBeta()) { + branchChoisBox.getSelectionModel().select(1); + } else { + branchChoisBox.getSelectionModel().select(0); + } + + setLocalUI(); + applyColor(); + } + + @FXML + private void playbtnclicked() { + // TODO rework when #19 is coming + + if (System.getProperty("os.name").contains("Linux")) { + String line; + String output = ""; + Process p; + try { + p = Runtime.getRuntime().exec("which vlc"); + BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); + while ((line = input.readLine()) != null) { + output = line; + } + LOGGER.info(output); + input.close(); + } catch (IOException e1) { + e1.printStackTrace(); + } + if (output.contains("which: no vlc") || output == "") { + JFXInfoDialog vlcInfoDialog = new JFXInfoDialog("Info", vlcNotInstalled, dialogBtnStyle, 350, 200, main.getPane()); + vlcInfoDialog.show(); + } else { + try { + Runtime.getRuntime().exec(new String[] { "vlc", streamUrl }); // TODO switch to ProcessBuilder + } catch (IOException e) { + showErrorMsg(errorPlay, e); + } + } + + } else if (System.getProperty("os.name").contains("Windows") || System.getProperty("os.name").contains("Mac OS X")) { + try { + Desktop.getDesktop().open(new File(streamUrl)); + } catch (IOException e) { + showErrorMsg(errorPlay, e); + } + } else { + LOGGER.error(System.getProperty("os.name") + ", OS is not supported, please contact a developer! "); + } + } + + @FXML + private void openfolderbtnclicked() { + String dest = new File(streamUrl).getParentFile().getAbsolutePath(); + if (!System.getProperty("os.name").contains("Linux")) { + try { + Desktop.getDesktop().open(new File(dest)); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + @FXML + private void returnBtnclicked(){ + filmsTreeTable.getSelectionModel().select(last); + } + + @FXML + private void forwardBtnclicked(){ + filmsTreeTable.getSelectionModel().select(next); + } + + @FXML + private void aboutBtnAction() { + String bodyText = "cemu_UI by @Seil0 \nVersion: " + version + " (Build: " + buildNumber + ") \"" + + versionName + "\" \n" + infoText; + JFXInfoDialog aboutDialog = new JFXInfoDialog("Project HomeFlix", bodyText, dialogBtnStyle, 350, 200, main.getPane()); + aboutDialog.show(); + } + + @FXML + private void settingsBtnclicked(){ + if(settingsTrue == false){ + settingsScrollPane.setVisible(true); + settingsTrue = true; + }else{ + settingsScrollPane.setVisible(false); + saveSettings(); + settingsTrue = false; + } + } + + @FXML + private void debugBtnclicked(){ + //for testing + } + + @FXML + private void addDirectoryBtnAction(){ + File selectedFolder = directoryChooser.showDialog(null); + if (selectedFolder != null && selectedFolder.exists()) { + addSource(selectedFolder.getPath(), "local"); + dbController.refreshDataBase(); + } else { + LOGGER.error("The selected folder dosen't exist!"); + } + } + + @FXML + private void addStreamSourceBtnAction(){ + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Open Resource File"); + File selectedFile = fileChooser.showOpenDialog(main.getPrimaryStage()); + if (selectedFile != null && selectedFile.exists()) { + addSource(selectedFile.getPath(), "stream"); + dbController.refreshDataBase(); + } else { + LOGGER.error("The selected file dosen't exist!"); + } + } + + @FXML + private void colorPickerAction(){ + editColor(colorPicker.getValue().toString()); + applyColor(); + } + + @FXML + private void updateBtnAction(){ + updateController = new UpdateController(this, buildNumber, useBeta); + Thread updateThread = new Thread(updateController); + updateThread.setName("Updater"); + updateThread.start(); + } + + @FXML + private void autoUpdateToggleBtnAction(){ + if (autoUpdate) { + setAutoUpdate(false); + } else { + setAutoUpdate(true); + } + saveSettings(); + } + + // refresh the selected child of the root node + private void refreshTable() { + filmRoot.getChildren().get(indexTable).setValue(filmsList.get(indexList)); + } + + /** + * add data from films-list to films-table + */ + public void addDataUI() { + + for (FilmTabelDataType element : filmsList) { + + // only if the entry contains a season and a episode it's a valid series + if (!element.getSeason().isEmpty() && !element.getEpisode().isEmpty()) { +// System.out.println("Found Series: " + element.getTitle()); + // check if there is a series node to add the item + for (int i = 0; i < filmRoot.getChildren().size(); i++) { + if (filmRoot.getChildren().get(i).getValue().getTitle().equals(element.getTitle())) { +// System.out.println("Found a root node to add child"); +// System.out.println("Adding: " + element.getStreamUrl()); + TreeItem episodeNode = new TreeItem<>(new FilmTabelDataType(element.getStreamUrl(), + element.getTitle(), element.getSeason(), element.getEpisode(), element.getFavorite(), + element.getCached(), element.getImage())); + filmRoot.getChildren().get(i).getChildren().add(episodeNode); + } else if (i == filmRoot.getChildren().size() - 1) { +// System.out.println("Create a root node to add child"); +// System.out.println("Adding: " + element.getStreamUrl()); + TreeItem seriesRootNode = new TreeItem<>(new FilmTabelDataType(element.getStreamUrl(), + element.getTitle(), "", "", element.getFavorite(), element.getCached(), element.getImage())); + filmRoot.getChildren().add(seriesRootNode); + } + } + } else { + filmRoot.getChildren().add(new TreeItem(element)); // add data to root-node + } + } + } + + // add a source to the sources table on the settings pane + public void addSourceToTable(String path, String mode) { + sourcesList.add(new SourceDataType(path, mode)); + sourceRoot.getChildren().add(new TreeItem(sourcesList.get(sourcesList.size() - 1))); // adds data to root-node + } + + // add a source to the newsources list + public void addSource(String path, String mode) { + JsonObject source = null; + JsonArray newsources = null; + + try { + // read old array + newsources = Json.parse(new FileReader(main.getDirectory() + "/sources.json")).asArray(); + + // add new source + Writer writer = new FileWriter(main.getDirectory() + "/sources.json"); + source = Json.object().add("path", path).add("mode", mode); + newsources.add(source); + newsources.writeTo(writer); + writer.close(); + } catch (IOException e) { + LOGGER.error(e); + } + } + + //set color of UI-Elements + private void applyColor() { + String style = "-fx-background-color: #" + getColor() + ";"; + String btnStyleBlack = "-fx-button-type: RAISED; -fx-background-color: #" + getColor() + "; -fx-text-fill: BLACK;"; + String btnStyleWhite = "-fx-button-type: RAISED; -fx-background-color: #" + getColor() + "; -fx-text-fill: WHITE;"; + BigInteger icolor = new BigInteger(getColor(), 16); + BigInteger ccolor = new BigInteger("78909cff", 16); + + sideMenuVBox.setStyle(style); + topHBox.setStyle(style); + searchTextField.setFocusColor(Color.valueOf(getColor())); + + if (icolor.compareTo(ccolor) == -1) { + dialogBtnStyle = btnStyleWhite; + settingsBtn.setStyle("-fx-text-fill: WHITE;"); + aboutBtn.setStyle("-fx-text-fill: WHITE;"); + debugBtn.setStyle("-fx-text-fill: WHITE;"); + addDirectoryBtn.setStyle(btnStyleWhite); + addStreamSourceBtn.setStyle(btnStyleWhite); + updateBtn.setStyle(btnStyleWhite); + playbtn.setStyle(btnStyleWhite); + openfolderbtn.setStyle(btnStyleWhite); + returnBtn.setStyle(btnStyleWhite); + forwardBtn.setStyle(btnStyleWhite); + playbtn.setGraphic(play_arrow_white); + returnBtn.setGraphic(skip_previous_white); + forwardBtn.setGraphic(skip_next_white); + menuHam.getStyleClass().add("jfx-hamburgerW"); + } else { + dialogBtnStyle = btnStyleBlack; + settingsBtn.setStyle("-fx-text-fill: BLACK;"); + aboutBtn.setStyle("-fx-text-fill: BLACK;"); + debugBtn.setStyle("-fx-text-fill: BLACK;"); + addDirectoryBtn.setStyle(btnStyleBlack); + addStreamSourceBtn.setStyle(btnStyleBlack); + updateBtn.setStyle(btnStyleBlack); + playbtn.setStyle(btnStyleBlack); + openfolderbtn.setStyle(btnStyleBlack); + returnBtn.setStyle(btnStyleBlack); + forwardBtn.setStyle(btnStyleBlack); + playbtn.setGraphic(play_arrow_black); + returnBtn.setGraphic(skip_previous_black); + forwardBtn.setGraphic(skip_next_black); + menuHam.getStyleClass().add("jfx-hamburgerB"); + } + } + + // slide in in 400ms + private void sideMenuSlideIn() { + sideMenuVBox.setVisible(true); + TranslateTransition translateTransition = new TranslateTransition(Duration.millis(400), sideMenuVBox); + translateTransition.setFromX(-150); + translateTransition.setToX(0); + translateTransition.play(); + } + + // slide out in 400ms + private void sideMenuSlideOut() { + TranslateTransition translateTransition = new TranslateTransition(Duration.millis(400), sideMenuVBox); + translateTransition.setFromX(0); + translateTransition.setToX(-150); + translateTransition.play(); + } + + void setLocalUI() { + switch (getLocal()) { + case "en_US": + setBundle(ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.US)); // us_English + languageChoisBox.getSelectionModel().select(0); + break; + case "de_DE": + setBundle(ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.GERMAN)); // German + languageChoisBox.getSelectionModel().select(1); + break; + default: + setBundle(ResourceBundle.getBundle("locals.HomeFlix-Local", Locale.US)); // default local + languageChoisBox.getSelectionModel().select(0); + break; + } + aboutBtn.setText(getBundle().getString("info")); + settingsBtn.setText(getBundle().getString("settings")); + searchTextField.setPromptText(getBundle().getString("tfSearch")); + openfolderbtn.setText(getBundle().getString("openFolder")); + updateBtn.setText(getBundle().getString("checkUpdates")); + addDirectoryBtn.setText(getBundle().getString("addDirectory")); + addStreamSourceBtn.setText(getBundle().getString("addStreamSource")); + homeflixSettingsLbl.setText(getBundle().getString("homeflixSettingsLbl")); + mainColorLbl.setText(getBundle().getString("mainColorLbl")); + fontsizeLbl.setText(getBundle().getString("fontsizeLbl")); + languageLbl.setText(getBundle().getString("languageLbl")); + autoUpdateToggleBtn.setText(getBundle().getString("autoUpdate")); + branchLbl.setText(getBundle().getString("branchLbl")); + columnStreamUrl.setText(getBundle().getString("columnStreamUrl")); + columnTitle.setText(getBundle().getString("columnName")); + columnSeason.setText(getBundle().getString("columnSeason")); + columnEpisode.setText(getBundle().getString("columnEpisode")); + columnFavorite.setText(getBundle().getString("columnFavorite")); + errorPlay = getBundle().getString("errorPlay"); + errorLoad = getBundle().getString("errorLoad"); + errorSave = getBundle().getString("errorSave"); + infoText = getBundle().getString("infoText"); + vlcNotInstalled = getBundle().getString("vlcNotInstalled"); + } + + // TODO remove after #19 has landed + public void showErrorMsg(String msg, Exception exception) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("Error"); + alert.setHeaderText(""); + alert.setContentText(msg); + alert.initOwner(main.getPrimaryStage()); + + // Create expandable Exception. + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + exception.printStackTrace(pw); + String exceptionText = sw.toString(); + + TextArea textArea = new TextArea(exceptionText); + textArea.setEditable(false); + textArea.setWrapText(true); + + textArea.setMaxWidth(Double.MAX_VALUE); + textArea.setMaxHeight(Double.MAX_VALUE); + GridPane.setVgrow(textArea, Priority.ALWAYS); + GridPane.setHgrow(textArea, Priority.ALWAYS); + + GridPane expContent = new GridPane(); + expContent.setMaxWidth(Double.MAX_VALUE); + expContent.add(textArea, 0, 1); + + // Set expandable Exception into the dialog pane. + alert.getDialogPane().setExpandableContent(expContent); + alert.showAndWait(); + LOGGER.error("An error occurred", exception); + } + + // save settings + public void saveSettings() { + LOGGER.info("saving settings ..."); + try { + props.setProperty("color", getColor()); + props.setProperty("autoUpdate", String.valueOf(isAutoUpdate())); + props.setProperty("useBeta", String.valueOf(isUseBeta())); + props.setProperty("size", getSize().toString()); + props.setProperty("local", getLocal()); + props.setProperty("ratingSortType", columnFavorite.getSortType().toString()); + + OutputStream outputStream = new FileOutputStream(main.getConfigFile()); // new output-stream + props.storeToXML(outputStream, "Project HomeFlix settings"); // writes new .xml + outputStream.close(); + } catch (IOException e) { + LOGGER.error(errorLoad, e); + } + } + + // load settings + public void loadSettings() { + LOGGER.info("loading settings ..."); + + try { + InputStream inputStream = new FileInputStream(main.getConfigFile()); + props.loadFromXML(inputStream); // new input-stream from .xml + + try { + setColor(props.getProperty("color")); + } catch (Exception e) { + LOGGER.error("cloud not load color", e); + setColor(""); + } + + try { + setSize(Double.parseDouble(props.getProperty("size"))); + } catch (Exception e) { + LOGGER.error("cloud not load fontsize", e); + setSize(17.0); + } + + 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 { + setLocal(props.getProperty("local")); + } catch (Exception e) { + LOGGER.error("cloud not load local", e); + setLocal(System.getProperty("user.language") + "_" + System.getProperty("user.country")); + } + + try { + setRatingSortType(props.getProperty("ratingSortType")); + } catch (Exception e) { + LOGGER.error("cloud not load autoUpdate", e); + setRatingSortType(""); + } + + inputStream.close(); + } catch (IOException e) { + LOGGER.error(errorSave, e); + } + + // try loading the omdbAPI key + try { + InputStream in = getClass().getClassLoader().getResourceAsStream("apiKeys.json"); + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + JsonObject apiKeys = Json.parse(reader).asObject(); + omdbAPIKey = apiKeys.getString("omdbAPIKey", ""); + } catch (Exception e) { + LOGGER.error("Cloud not load the omdbAPI key. Please contact the developer!", e); + } + } + + // if AutoUpdate, then check for updates + private void checkAutoUpdate() { + + if (isAutoUpdate()) { + try { + LOGGER.info("AutoUpdate: looking for updates on startup ..."); + updateController = new UpdateController(this, buildNumber, useBeta); + Thread updateThread = new Thread(updateController); + updateThread.setName("Updater"); + updateThread.start(); + updateThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + // cuts 0x of the Color-pickers return value + private void editColor(String input) { + StringBuilder sb = new StringBuilder(input); + sb.delete(0, 2); + this.color = sb.toString(); + saveSettings(); + } + + // getter and setter + public DBController getDbController() { + return dbController; + } + + public void setColor(String input) { + this.color = input; + } + + public String getColor() { + return color; + } + + public String getTitle() { + return title; + } + + public String getStreamUrl() { + return streamUrl; + } + + public void setSize(Double input) { + this.size = input; + } + + public Double getSize() { + return size; + } + + public int getIndexTable() { + return indexTable; + } + + public int getIndexList() { + return indexList; + } + + public void setAutoUpdate(boolean input) { + this.autoUpdate = input; + } + + public boolean isAutoUpdate() { + return autoUpdate; + } + + public boolean isUseBeta() { + return useBeta; + } + + public void setUseBeta(boolean useBeta) { + this.useBeta = useBeta; + } + + public void setLocal(String input) { + this.local = input; + } + + public String getLocal() { + return local; + } + + public String getOmdbAPIKey() { + return omdbAPIKey; + } + + public ObservableList getFilmsList() { + return filmsList; + } + + public ObservableList getSourcesList() { + return sourcesList; + } + + public String getRatingSortType() { + return ratingSortType; + } + + public void setRatingSortType(String ratingSortType) { + this.ratingSortType = ratingSortType; + } + + public ResourceBundle getBundle() { + return bundle; + } + + public void setBundle(ResourceBundle bundle) { + this.bundle = bundle; + } + + public TreeTableView getFilmsTreeTable() { + return filmsTreeTable; + } + + public TextFlow getTextFlow() { + return textFlow; + } + + public ImageView getPosterImageView() { + return posterImageView; + } + + public JFXButton getUpdateBtn() { + return updateBtn; + } + + public TreeItem getFilmRoot() { + return filmRoot; + } + + public TreeItem getSourceRoot() { + return sourceRoot; + } +} diff --git a/src/main/java/kellerkinder/HomeFlix/controller/DBController.java b/src/main/java/kellerkinder/HomeFlix/controller/DBController.java new file mode 100644 index 0000000..36fd8fc --- /dev/null +++ b/src/main/java/kellerkinder/HomeFlix/controller/DBController.java @@ -0,0 +1,590 @@ +/** + * Project-HomeFlix + * + * Copyright 2016-2018 <@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 kellerkinder.HomeFlix.controller; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; + +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; +import javafx.scene.text.Text; +import kellerkinder.HomeFlix.application.Main; +import kellerkinder.HomeFlix.application.MainWindowController; +import kellerkinder.HomeFlix.datatypes.SourceDataType; +import kellerkinder.HomeFlix.datatypes.FilmTabelDataType; + +public class DBController { + + public DBController(Main main, MainWindowController mainWindowController) { + this.main = main; + this.mainWindowController = mainWindowController; + } + + private MainWindowController mainWindowController; + private Main main; + private String DB_PATH = System.getProperty("user.home") + "\\Documents\\HomeFlix" + "\\" + "Homeflix.db"; //path to database file + private Image favorite_black = new Image("icons/ic_favorite_black_18dp_1x.png"); + private Image favorite_border_black = new Image("icons/ic_favorite_border_black_18dp_1x.png"); + private List filmsdbAll = new ArrayList(); + private List filmsdbDir = new ArrayList(); + private List filmsdbStreamURL = new ArrayList(); // needed + private List filmsStreamURL = new ArrayList(); // needed + private Connection connection = null; + private static final Logger LOGGER = LogManager.getLogger(DBController.class.getName()); + + public void init() { + LOGGER.info("<========== starting loading sql ==========>"); + initDatabaseConnection(); + createDatabase(); + refreshDataBase(); + LOGGER.info("<========== finished loading sql ==========>"); + } + + private void initDatabaseConnection() { + DB_PATH = main.getDirectory() + "/Homeflix.db"; + try { + // create a database connection + connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH); + connection.setAutoCommit(false); //AutoCommit to false -> manual commit is active + } catch (SQLException e) { + // if the error message is "out of memory", it probably means no database file is found + LOGGER.error("error while loading the ROM database", e); + } + LOGGER.info("ROM database loaded successfull"); + } + + /** + * if tables don't exist create them + * cache table: streamUrl is primary key + */ + private void createDatabase() { + try { + Statement stmt = connection.createStatement(); + stmt.executeUpdate("create table if not exists films (streamUrl, title, season, episode, favorite, cached)"); + stmt.executeUpdate("create table if not exists cache (" + + "streamUrl, Title, Year, Rated, Released, Runtime, Genre, Director, Writer," + + " Actors, Plot, Language, Country, Awards, Metascore, imdbRating, imdbVotes," + + " imdbID, Type, Poster, Response)"); + stmt.close(); + } catch (SQLException e) { + LOGGER.error(e); + } + } + + private void loadDatabase() { + // get all entries from the table + try { + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT * FROM films"); + while (rs.next()) { + filmsdbDir.add(rs.getString("title")); + filmsdbStreamURL.add(rs.getString("streamUrl")); + } + stmt.close(); + rs.close(); + } catch (SQLException e) { + LOGGER.error("Ups! an error occured!", e); + } + + // add all entries to filmsAll and filmsdbAl, for later comparing + filmsdbAll.addAll(filmsdbDir); + LOGGER.info("films in directory: " + filmsStreamURL.size()); + LOGGER.info("filme in db: " + filmsdbStreamURL.size()); + } + + // load the sources from sources.json + private void loadSources() { + // remove sources from table + mainWindowController.getSourcesList().removeAll(mainWindowController.getSourcesList()); + mainWindowController.getSourceRoot().getChildren().removeAll(mainWindowController.getSourceRoot().getChildren()); + + try { + JsonArray sources = Json.parse(new FileReader(main.getDirectory() + "/sources.json")).asArray(); + for (JsonValue source : sources) { + String path = source.asObject().getString("path", ""); + String mode = source.asObject().getString("mode", ""); + mainWindowController.addSourceToTable(path, mode); // add source to source-table + if (mode.equals("local")) { + for (File file : new File(path).listFiles()) { + if (file.isFile()) { + // get all files (films) + filmsStreamURL.add(file.getPath()); + } else { + // get all folders (series) + for (File season : file.listFiles()) { + if (season.isDirectory()) { + for (File episode : season.listFiles()) { + if (!filmsdbStreamURL.contains(episode.getPath())) { + filmsStreamURL.add(episode.getPath()); + } + } + } + } + } + } + LOGGER.info("added files from: " + path); + } else { + // getting all entries from the streaming lists + try { + JsonObject object = Json.parse(new FileReader(path)).asObject(); + JsonArray items = object.get("entries").asArray(); + for (JsonValue item : items) { + filmsStreamURL.add(item.asObject().getString("streamUrl", "")); + } + LOGGER.info("added films from: " + path); + } catch (IOException e) { + LOGGER.error(e); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + // loading data from database to mainWindowController + private void loadDataToMWC() { + LOGGER.info("loading data to mwc ..."); + try { + //load local Data + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT * FROM films ORDER BY title"); + while (rs.next()) { +// System.out.println(rs.getString("title") + "Season:" + rs.getString("season") + ":"); + if (rs.getBoolean("favorite") == true) { + mainWindowController.getFilmsList().add(new FilmTabelDataType(rs.getString("streamUrl"), + rs.getString("title"), rs.getString("season"), rs.getString("episode") ,rs.getBoolean("favorite"), + rs.getBoolean("cached"), new ImageView(favorite_black))); + } else { + mainWindowController.getFilmsList().add(new FilmTabelDataType(rs.getString("streamUrl"), + rs.getString("title"), rs.getString("season"), rs.getString("episode"), rs.getBoolean("favorite"), + rs.getBoolean("cached"), new ImageView(favorite_border_black))); + } + } + stmt.close(); + rs.close(); + } catch (SQLException e) { + LOGGER.error("Ups! an error occured!", e); + } + + LOGGER.info("loading data to the GUI ..."); + mainWindowController.addDataUI(); + } + + /** + * refresh data in mainWindowController localFilms and streamingFilms + * @param streamUrl of the film + * @param index of the film in LocalFilms list + */ + public void refresh(String streamUrl, int indexList) { + LOGGER.info("refresh ..."); + try { + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT * FROM films WHERE streamUrl = \"" + streamUrl + "\";"); + + if (rs.getBoolean("favorite") == true) { + mainWindowController.getFilmsList().set(indexList, new FilmTabelDataType(rs.getString("streamUrl"), + rs.getString("title"), rs.getString("season"), rs.getString("episode"), rs.getBoolean("favorite"), + rs.getBoolean("cached"), new ImageView(favorite_black))); + } else { + mainWindowController.getFilmsList().set(indexList, new FilmTabelDataType(rs.getString("streamUrl"), + rs.getString("title"), rs.getString("season"), rs.getString("episode"), rs.getBoolean("favorite"), + rs.getBoolean("cached"), new ImageView(favorite_border_black))); + } + + rs.close(); + stmt.close(); + } catch (Exception e) { + LOGGER.error("Ups! error while refreshing mwc!", e); + } + } + + /** + * refresh database to contain all (new added) entries + * refresh the MainWindowController content, + * to contain all (new added) entries from the database + */ + public void refreshDataBase() { + LOGGER.info("refreshing the Database ..."); + + // clean all ArraLists + filmsdbAll.removeAll(filmsdbAll); + filmsdbDir.removeAll(filmsdbDir); + filmsdbStreamURL.removeAll(filmsdbStreamURL); + filmsStreamURL.removeAll(filmsStreamURL); + + loadSources(); // reload all sources + loadDatabase(); // reload all films saved in the DB + + + try { + checkAddEntry(); + checkRemoveEntry(); + } catch (Exception e) { + LOGGER.error("Error while refreshing the database", e); + } + + // remove all films from the mwc lists + mainWindowController.getFilmsList().removeAll(mainWindowController.getFilmsList()); + mainWindowController.getFilmRoot().getChildren().removeAll(mainWindowController.getFilmRoot().getChildren()); + + loadDataToMWC(); // load the new data to the mwc + } + + /** + * check if there are any entries that have been removed from the film-directory + */ + private void checkRemoveEntry() { + LOGGER.info("checking for entrys to remove to DB ..."); + + try { + Statement stmt = connection.createStatement(); + + for (String entry : filmsdbStreamURL) { + if (!filmsStreamURL.contains(entry)) { + System.out.println(filmsdbStreamURL + "\n"); + System.out.println(filmsStreamURL); + stmt.executeUpdate("delete from films where streamUrl = \"" + entry + "\""); + connection.commit(); + LOGGER.info("removed \"" + entry + "\" from database"); + } + } + + stmt.close(); + } catch (Exception e) { + LOGGER.error(e); + } + } + + /** + * check if there are new films in the film-directory + * @throws SQLException + * @throws FileNotFoundException + * @throws IOException + */ + private void checkAddEntry() throws SQLException, FileNotFoundException, IOException { + Statement stmt = connection.createStatement(); + PreparedStatement ps = connection.prepareStatement("insert into films values (?, ?, ?, ?, ?, ?)"); + LOGGER.info("checking for entrys to add to DB ..."); + + // source is a single source of the sources list + for (SourceDataType source : mainWindowController.getSourcesList()) { + // if it's a local source check the folder for new film + if (source.getMode().equals("local")) { + for (File file : new File(source.getPath()).listFiles()) { + + if (file.isFile()) { + // get all files (films) + if (!filmsdbStreamURL.contains(file.getPath())) { + stmt.executeUpdate("insert into films values (" + + "'" + file.getPath() + "'," + + "'" + cutOffEnd(file.getName()) + "', '', '', 0, 0)"); + connection.commit(); + stmt.close(); + LOGGER.info("Added \"" + file.getName() + "\" to database"); + filmsdbStreamURL.add(file.getPath()); + } + } else { + // get all folders (series) + int sn = 1; + for (File season : file.listFiles()) { + if (season.isDirectory()) { + int ep = 1; + for (File episode : season.listFiles()) { + if (!filmsdbStreamURL.contains(episode.getPath())) { + LOGGER.info("Added \"" + file.getName() + "\", Episode: " + episode.getName() + " to database"); + stmt.executeUpdate("insert into films values (" + + "'" + episode.getPath() + "'," + + "'" + cutOffEnd(file.getName()) + "','" + sn + "','" + ep + "', 0, 0)"); + connection.commit(); + stmt.close(); + filmsStreamURL.add(episode.getPath()); + filmsdbStreamURL.add(episode.getPath()); + ep++; + } + } + sn++; + } + } + } + + } + } else { + // if it's a streaming source check the file for new films + for (String entry : filmsStreamURL) { + if (!filmsdbStreamURL.contains(entry)) { + JsonArray items = Json.parse(new FileReader(source.getPath())).asObject().get("entries").asArray(); + // for each item, check if it's the needed + for (JsonValue item : items) { + String streamUrl = item.asObject().getString("streamUrl", ""); + String title = item.asObject().getString("title", ""); + + // if it's the needed add it to the database + if (streamUrl.equals(entry)) { + ps.setString(1, streamUrl); + ps.setString(2, title); + ps.setString(3, item.asObject().getString("season", "")); + ps.setString(4, item.asObject().getString("episode", "")); + ps.setInt(5, 0); + ps.setBoolean(6, false); + ps.addBatch(); // adds the entry + LOGGER.info("Added \"" + title + "\" to database"); + filmsdbStreamURL.add(streamUrl); + } + } + } + } + ps.executeBatch(); + connection.commit(); + ps.close(); + } + } + } + + // prints all entries from the database to the console + public void printAllDBEntriesDEBUG() { + System.out.println("Outputting all entries ... \n"); + try { + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT * FROM films"); + while (rs.next()) { + System.out.println(rs.getString("streamUrl")); + System.out.println(rs.getString("title")); + System.out.println(rs.getString("season")); + System.out.println(rs.getString("episode")); + System.out.println(rs.getString("rating")); + System.out.println(rs.getString("cached") + "\n"); + } + stmt.close(); + rs.close(); + } catch (SQLException e) { + LOGGER.error("An error occured, while printing all entries", e); + } + } + + /** + * update the database entry for the given film, favorite = 0 + * @param streamUrl URL of the film + */ + public void dislike(String streamUrl) { + LOGGER.info("dislike " + streamUrl); + try { + Statement stmt = connection.createStatement(); + stmt.executeUpdate("UPDATE films SET favorite=0 WHERE streamUrl=\"" + streamUrl + "\";"); + connection.commit(); + stmt.close(); + } catch (SQLException e) { + LOGGER.error("Ups! an error occured!", e); + } + } + + /** + * update the database entry for the given film, favorite = 1 + * @param streamUrl URL of the film + */ + public void like(String streamUrl) { + LOGGER.info("like " + streamUrl); + try { + Statement stmt = connection.createStatement(); + stmt.executeUpdate("UPDATE films SET favorite=1 WHERE streamUrl=\"" + streamUrl + "\";"); + connection.commit(); + stmt.close(); + } catch (SQLException e) { + LOGGER.error("Ups! an error occured!", e); + } + } + + /** + * update the database entry for the given film, cached = 1 + * @param streamUrl URL of the film + */ + void setCached(String streamUrl) { + try { + Statement stmt = connection.createStatement(); + stmt.executeUpdate("UPDATE films SET cached=1 WHERE streamUrl=\"" + streamUrl + "\";"); + connection.commit(); + stmt.close(); + } catch (SQLException e) { + LOGGER.error("Ups! an error occured!", e); + } + + refresh(streamUrl, mainWindowController.getIndexList()); + } + + /** + * add the received data to the cache table + * @param streamUrl URL of the film + * @param Title + * @param Year + * @param Rated + * @param Released + * @param Runtime + * @param Genre + * @param Director + * @param Writer + * @param Actors + * @param Plot + * @param Language + * @param Country + * @param Awards + * @param Metascore + * @param imdbRating + * @param Type + * @param imdbVotes + * @param imdbID + * @param Poster + * @param Response + * @throws SQLException + */ + void addCache( String streamUrl, String Title, String Year, String Rated, String Released, String Runtime, String Genre, String Director, + String Writer, String Actors, String Plot, String Language, String Country, String Awards, String Metascore, String imdbRating, + String Type, String imdbVotes, String imdbID, String Poster, String Response) { + try { + PreparedStatement ps = connection.prepareStatement("insert into cache values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); + + LOGGER.info("adding to cache: " + Title); + ps.setString(1,streamUrl); + ps.setString(2,Title); + ps.setString(3,Year); + ps.setString(4,Rated); + ps.setString(5,Released); + ps.setString(6,Runtime); + ps.setString(7,Genre); + ps.setString(8,Director); + ps.setString(9,Writer); + ps.setString(10,Actors); + ps.setString(11,Plot); + ps.setString(12,Language); + ps.setString(13,Country); + ps.setString(14,Awards); + ps.setString(15,Metascore); + ps.setString(16,imdbRating); + ps.setString(17,imdbVotes); + ps.setString(18,imdbID); + ps.setString(19,Type); + ps.setString(20,Poster); + ps.setString(21,Response); + ps.addBatch(); + ps.executeBatch(); + connection.commit(); + ps.close(); + LOGGER.info("done!"); + } catch (Exception e) { + LOGGER.error(e); + } + } + + /** + * sets the cached data to mwc's TextFlow + * @param streamUrl URL of the film + */ + public void readCache(String streamUrl) { + try { + Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT * FROM cache WHERE streamUrl=\"" + streamUrl + "\";"); + ArrayList nameText = new ArrayList(); + ArrayList responseText = new ArrayList(); + String fontFamily = main.getFONT_FAMILY(); + Image im; + int fontSize = (int) Math.round(mainWindowController.size); + int j = 2; + + nameText.add(0, new Text(mainWindowController.getBundle().getString("title") + ": ")); + nameText.add(1, new Text(mainWindowController.getBundle().getString("year") + ": ")); + nameText.add(2, new Text(mainWindowController.getBundle().getString("rating") + ": ")); + nameText.add(3, new Text(mainWindowController.getBundle().getString("publishedOn") + ": ")); + nameText.add(4, new Text(mainWindowController.getBundle().getString("duration") + ": ")); + nameText.add(5, new Text(mainWindowController.getBundle().getString("genre") + ": ")); + nameText.add(6, new Text(mainWindowController.getBundle().getString("director") + ": ")); + nameText.add(7, new Text(mainWindowController.getBundle().getString("writer") + ": ")); + nameText.add(8, new Text(mainWindowController.getBundle().getString("actors") + ": ")); + nameText.add(9, new Text(mainWindowController.getBundle().getString("plot") + ": ")); + nameText.add(10, new Text(mainWindowController.getBundle().getString("language") + ": ")); + nameText.add(11, new Text(mainWindowController.getBundle().getString("country") + ": ")); + nameText.add(12, new Text(mainWindowController.getBundle().getString("awards") + ": ")); + nameText.add(13, new Text(mainWindowController.getBundle().getString("metascore") + ": ")); + nameText.add(14, new Text(mainWindowController.getBundle().getString("imdbRating") + ": ")); + nameText.add(15, new Text(mainWindowController.getBundle().getString("type") + ": ")); + + for (int i = 0; i < 15; i++) { + responseText.add(new Text(rs.getString(j) + "\n")); + j++; + } + responseText.add(new Text(rs.getString(19) + "\n")); + im = new Image(new File(rs.getString(20)).toURI().toString()); + + stmt.close(); + rs.close(); + + for (int i = 0; i < nameText.size(); i++) { + nameText.get(i).setFont(Font.font(fontFamily, FontWeight.BOLD, fontSize)); + responseText.get(i).setFont(Font.font(fontFamily, fontSize)); + } + + mainWindowController.getTextFlow().getChildren().remove(0, + mainWindowController.getTextFlow().getChildren().size()); + + for (int i = 0; i < nameText.size(); i++) { + mainWindowController.getTextFlow().getChildren().addAll(nameText.get(i), responseText.get(i)); + } + + try { + mainWindowController.getPosterImageView().setImage(im); + } catch (Exception e) { + mainWindowController.getPosterImageView().setImage(new Image("resources/icons/close_black_2048x2048.png")); + LOGGER.error(e); + } + + } catch (SQLException e) { + LOGGER.error("Ups! an error occured!", e); + } + } + + // removes the ending + private String cutOffEnd(String str) { + if (str == null) return null; + int pos = str.lastIndexOf("."); + if (pos == -1) return str; + return str.substring(0, pos); + } + +} diff --git a/src/main/java/kellerkinder/HomeFlix/controller/OMDbAPIController.java b/src/main/java/kellerkinder/HomeFlix/controller/OMDbAPIController.java new file mode 100644 index 0000000..6e8f5cd --- /dev/null +++ b/src/main/java/kellerkinder/HomeFlix/controller/OMDbAPIController.java @@ -0,0 +1,126 @@ +/** + * Project-HomeFlix + * + * Copyright 2018 <@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 kellerkinder.HomeFlix.controller; + +import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import javax.imageio.ImageIO; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonObject; + +import javafx.application.Platform; +import kellerkinder.HomeFlix.application.Main; +import kellerkinder.HomeFlix.application.MainWindowController; + +public class OMDbAPIController implements Runnable { + + private MainWindowController mainWindowController; + private DBController dbController; + private Main main; + private String[] responseString = new String[20]; + private String URL = "https://www.omdbapi.com/?apikey="; + private static final Logger LOGGER = LogManager.getLogger(MainWindowController.class.getName()); + + public OMDbAPIController(MainWindowController mainWindowController, DBController dbController, Main main){ + this.mainWindowController = mainWindowController; + this.dbController = dbController; + this.main = main; + + + } + + @Override + public void run() { + String output = null; + String posterPath = null; + + // get by title, TODO implement search + try { + URL apiUrl = new URL(URL + mainWindowController.getOmdbAPIKey() + "&t=" + + mainWindowController.getTitle().replace(" ", "%20")); + BufferedReader ina = new BufferedReader(new InputStreamReader(apiUrl.openStream())); + output = ina.readLine(); + ina.close(); + LOGGER.info("response from " + URL + " was valid"); + LOGGER.info(output); + } catch (IOException e) { + LOGGER.error("error while making api request or reading response"); + LOGGER.error("response from " + URL + " was: \n" + output, e); + return; + } + + JsonObject object = Json.parse(output).asObject(); + + responseString[0] = object.getString("Title", ""); + responseString[1] = object.getString("Year", ""); + responseString[2] = object.getString("Rated", ""); + responseString[3] = object.getString("Released", ""); + responseString[4] = object.getString("Runtime", ""); + responseString[5] = object.getString("Genre", ""); + responseString[6] = object.getString("Director", ""); + responseString[7] = object.getString("Writer", ""); + responseString[8] = object.getString("Actors", ""); + responseString[9] = object.getString("Plot", ""); + responseString[10] = object.getString("Language", ""); + responseString[11] = object.getString("Country", ""); + responseString[12] = object.getString("Awards", ""); + responseString[13] = object.getString("Metascore", ""); + responseString[14] = object.getString("imdbRating", ""); + responseString[15] = object.getString("Type", ""); + responseString[16] = object.getString("imdbVotes", ""); + responseString[17] = object.getString("imdbID", ""); + responseString[18] = object.getString("Poster", ""); + responseString[19] = object.getString("Response", ""); + + //resize the image to fit in the posterImageView and add it to the cache + try { + BufferedImage originalImage = ImageIO.read(new URL(responseString[18])); //change path to where file is located + posterPath = main.getPosterCache() + "/" + mainWindowController.getTitle() + ".png"; + ImageIO.write(originalImage, "png", new File(posterPath)); + LOGGER.info("adding poster to cache: "+posterPath); + } catch (Exception e) { + LOGGER.error(e); + } + + // adding strings to the cache + dbController.addCache(mainWindowController.getStreamUrl(), responseString[0], responseString[1], + responseString[2], responseString[3], responseString[4], responseString[5], responseString[6], + responseString[7], responseString[8], responseString[9], responseString[10], responseString[11], + responseString[12], responseString[13], responseString[14], responseString[15], responseString[16], + responseString[17], posterPath, responseString[19]); + dbController.setCached(mainWindowController.getStreamUrl()); + + // load data to the MainWindowController + Platform.runLater(() -> { + dbController.readCache(mainWindowController.getStreamUrl()); + }); + } +} diff --git a/src/main/java/kellerkinder/HomeFlix/controller/UpdateController.java b/src/main/java/kellerkinder/HomeFlix/controller/UpdateController.java new file mode 100644 index 0000000..a21b376 --- /dev/null +++ b/src/main/java/kellerkinder/HomeFlix/controller/UpdateController.java @@ -0,0 +1,163 @@ +/** + * Project-HomeFlix + * + * Copyright 2018 <@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 kellerkinder.HomeFlix.controller; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import javax.swing.ProgressMonitor; +import javax.swing.ProgressMonitorInputStream; + +import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; + +import javafx.application.Platform; +import kellerkinder.HomeFlix.application.MainWindowController; + +public class UpdateController implements Runnable { + + private MainWindowController mainWindowController; + private String buildNumber; + private String apiOutput; + private String updateBuildNumber; // tag_name from Github +// private String updateName; +// private String updateChanges; + private String browserDownloadUrl; // update download link + private String githubApiRelease = "https://api.github.com/repos/Seil0/Project-HomeFlix/releases/latest"; + private String githubApiBeta = "https://api.github.com/repos/Seil0/Project-HomeFlix/releases"; + + private URL githubApiUrl; + private boolean useBeta; + private static final Logger LOGGER = LogManager.getLogger(UpdateController.class.getName()); + + /** + * updater for Project HomeFlix based on cemu_UIs, checks for Updates and download it + */ + public UpdateController(MainWindowController mwc, String buildNumber, boolean useBeta) { + mainWindowController = mwc; + this.buildNumber = buildNumber; + this.useBeta = useBeta; + } + + @Override + public void run() { + LOGGER.info("beta:" + useBeta + "; checking for updates ..."); + Platform.runLater(() -> { + mainWindowController.getUpdateBtn().setText(mainWindowController.getBundle().getString("updateBtnChecking")); + }); + + try { + + 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(); + ina.close(); + } catch (IOException e) { + Platform.runLater(() -> { + LOGGER.error("could not check update version", e); + }); + } + + if (useBeta) { + JsonArray objectArray = Json.parse("{\"items\": " + apiOutput + "}").asObject().get("items").asArray(); + JsonValue object = objectArray.get(0); + JsonArray objectAssets = object.asObject().get("assets").asArray(); + + updateBuildNumber = object.asObject().getString("tag_name", ""); +// updateName = object.asObject().getString("name", ""); +// updateChanges = object.asObject().getString("body", ""); + + for (JsonValue asset : objectAssets) { + browserDownloadUrl = asset.asObject().getString("browser_download_url", ""); + } + + } else { + JsonObject object = Json.parse(apiOutput).asObject(); + 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); + + // Compares the program BuildNumber with the current BuildNumber if program + // BuildNumber < current BuildNumber then perform a update + int iversion = Integer.parseInt(buildNumber); + int iaktVersion = Integer.parseInt(updateBuildNumber.replace(".", "")); + + if (iversion >= iaktVersion) { + Platform.runLater(() -> { + mainWindowController.getUpdateBtn().setText(mainWindowController.getBundle().getString("updateBtnNoUpdateAvailable")); + }); + LOGGER.info("no update available"); + } else { + Platform.runLater(() -> { + mainWindowController.getUpdateBtn().setText(mainWindowController.getBundle().getString("updateBtnUpdateAvailable")); + }); + LOGGER.info("update available"); + LOGGER.info("download link: " + browserDownloadUrl); + try { + // open new Http connection, ProgressMonitorInputStream for downloading the data + HttpURLConnection connection = (HttpURLConnection) new URL(browserDownloadUrl).openConnection(); + ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(null, "Downloading...", connection.getInputStream()); + ProgressMonitor pm = pmis.getProgressMonitor(); + pm.setMillisToDecideToPopup(0); + pm.setMillisToPopup(0); + pm.setMinimum(0);// set beginning of the progress bar to 0 + pm.setMaximum(connection.getContentLength());// set the end to the file length + FileUtils.copyInputStreamToFile(pmis, new File("ProjectHomeFlix_update.jar")); // download update + org.apache.commons.io.FileUtils.copyFile(new File("ProjectHomeFlix_update.jar"), new File("ProjectHomeFlix.jar")); + org.apache.commons.io.FileUtils.deleteQuietly(new File("ProjectHomeFlix_update.jar")); // delete update + Runtime.getRuntime().exec("java -jar ProjectHomeFlix.jar"); // start again TODO consider ProcessBuilder to execute + System.exit(0); // finishes itself + } catch (IOException e) { + Platform.runLater(() -> { + LOGGER.info("could not download update files", e); + }); + } + } + + } + +} diff --git a/src/main/java/kellerkinder/HomeFlix/datatypes/FilmTabelDataType.java b/src/main/java/kellerkinder/HomeFlix/datatypes/FilmTabelDataType.java new file mode 100644 index 0000000..3bc51b1 --- /dev/null +++ b/src/main/java/kellerkinder/HomeFlix/datatypes/FilmTabelDataType.java @@ -0,0 +1,149 @@ +/** + * Project-HomeFlix + * + * Copyright 2016-2018 <@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 kellerkinder.HomeFlix.datatypes; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.scene.image.ImageView; + +public class FilmTabelDataType { + private final StringProperty streamUrl = new SimpleStringProperty(); + private final StringProperty title = new SimpleStringProperty(); + private final StringProperty season = new SimpleStringProperty(); + private final StringProperty episode = new SimpleStringProperty(); + private final BooleanProperty favorite = new SimpleBooleanProperty(); + private final BooleanProperty cached = new SimpleBooleanProperty(); + private final SimpleObjectProperty image = new SimpleObjectProperty<>(); + + + /** + * tableData is the data-type of tree-table-view + * @param streamUrl the concrete path to the file or the URL + * @param title title of the film + * @param season season if it's a series + * @param episode episode if it's a series + * @param favorite indicator for favorites, used for sorting the items + * @param cached indicator for caching status + * @param image favorite icon + */ + public FilmTabelDataType(final String streamUrl, final String title, final String season, final String episode, + final boolean favorite, final boolean cached, final ImageView image) { + this.streamUrl.set(streamUrl); + this.title.set(title); + this.season.set(season); + this.episode.set(episode); + this.favorite.set(favorite); + this.cached.set(cached); + this.image.set(image); + } + + public StringProperty streamUrlProperty(){ + return streamUrl; + } + + public StringProperty titleProperty(){ + return title; + } + + public StringProperty seasonProperty(){ + return season; + } + + public StringProperty episodeProperty(){ + return episode; + } + + public BooleanProperty favoriteProperty(){ + return favorite; + } + + public BooleanProperty cachedProperty(){ + return cached; + } + + public SimpleObjectProperty imageProperty(){ + return image; + } + + + public final String getStreamUrl() { + return streamUrlProperty().get(); + } + + public final String getTitle() { + return titleProperty().get(); + } + + public final String getSeason() { + return seasonProperty().get(); + } + + public final String getEpisode() { + return episodeProperty().get(); + } + + public final boolean getFavorite() { + return favoriteProperty().get(); + } + + public final boolean getCached(){ + return cachedProperty().get(); + } + + public final ImageView getImage() { + return imageProperty().get(); + } + + + public final void setStreamUrl(String streamUrl) { + streamUrlProperty().set(streamUrl); + } + + public final void setTitle(String title) { + titleProperty().set(title); + } + + public final void setSeason(String season) { + seasonProperty().set(season); + } + + public final void setEpisode(String season) { + episodeProperty().set(season); + } + + public final void setFavorite(boolean favorite) { + favoriteProperty().set(favorite); + } + + public final void setCached(boolean cached){ + cachedProperty().set(cached); + } + + public final void setImage(ImageView image) { + imageProperty().set(image); + } + + +} diff --git a/src/main/java/kellerkinder/HomeFlix/datatypes/SourceDataType.java b/src/main/java/kellerkinder/HomeFlix/datatypes/SourceDataType.java new file mode 100644 index 0000000..aab7fa5 --- /dev/null +++ b/src/main/java/kellerkinder/HomeFlix/datatypes/SourceDataType.java @@ -0,0 +1,64 @@ +/** + * Project-HomeFlix + * + * Copyright 2016-2018 <@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 kellerkinder.HomeFlix.datatypes; + +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + +public class SourceDataType { + private final StringProperty path = new SimpleStringProperty(); + private final StringProperty mode = new SimpleStringProperty(); + + /** + * data type for the source table + * @param path of the source + * @param mode of the source, stream or local + */ + public SourceDataType (final String path, final String mode) { + this.path.set(path); + this.mode.set(mode); + } + + public StringProperty pathProperty(){ + return path; + } + + public StringProperty modeProperty(){ + return mode; + } + + public final String getPath() { + return pathProperty().get(); + } + + public final String getMode() { + return modeProperty().get(); + } + + public final void setPath(String path) { + pathProperty().set(path); + } + + public final void setMode(String mode) { + modeProperty().set(mode); + } +} diff --git a/src/main/resources/css/MainWindow.css b/src/main/resources/css/MainWindow.css new file mode 100644 index 0000000..92eccee --- /dev/null +++ b/src/main/resources/css/MainWindow.css @@ -0,0 +1,109 @@ +/* + * HAMBURGER CSS + */ + +.jfx-hamburgerW StackPane { + -fx-background-color: white; + -fx-background-radius: 5px; +} + +.jfx-hamburgerB StackPane { + -fx-background-color: black; + -fx-background-radius: 5px; +} + +/* + * TREE TABLE CSS + */ + +.tree-table-view { + -fx-tree-table-color: rgba(0, 168, 204, 0.2); + -fx-tree-table-rippler-color: rgba(0, 168, 204, 0.4); +} + +.tree-table-view:focused .tree-table-row-cell:selected { + -fx-background-color: -fx-tree-table-color; + -fx-table-cell-border-color: -fx-tree-table-color; + -fx-text-fill: BLACK; +} + +.tree-table-view:focused .tree-table-row-cell:selected .tree-table-cell { + -fx-text-fill: BLACK; +} + +.tree-table-view .jfx-rippler { + -jfx-rippler-fill: -fx-tree-table-rippler-color; +} + +.tree-table-view .column-header, +.tree-table-view .column-header-background, +.tree-table-view .column-header-background .filler { + -fx-background-color: TRANSPARENT; +} + +.tree-table-view .column-header { + -fx-border-width: 0 1 0 1; + -fx-border-color: #F3F3F3; +} + +.tree-table-view .column-header .label { + -fx-text-fill: #000000; + -fx-padding: 12 0 12 0; +} + +.tree-table-view .column-header .arrow, .tree-table-view .column-header .sort-order-dot { + -fx-background-color: #000000; +} + +.tree-table-view .column-header:last-visible { + -fx-border-width: 0 2 0 1; +} + +.tree-table-view .column-header-background { + -fx-border-width: 0 0.0 1 0; + -fx-border-color: #F3F3F3; +} + +.tree-table-view .tree-table-cell { + -fx-border-width: 0 0 0 0; + -fx-padding: 12 4 8 4; +} + +.tree-table-view .column-overlay { + -fx-background-color: -fx-tree-table-color; +} + +.tree-table-view .column-resize-line, .tree-table-view .column-drag-header { + -fx-background-color: -fx-tree-table-rippler-color; +} + +.tree-table-view:focused { + -fx-background-color: -fx-tree-table-color, -fx-box-border, -fx-control-inner-background; + -fx-background-insets: -1.4, 0, 1; + -fx-background-radius: 1.4, 0, 0; + -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: #EE3523; +} \ No newline at end of file diff --git a/src/main/resources/fxml/MainWindow.fxml b/src/main/resources/fxml/MainWindow.fxml new file mode 100644 index 0000000..cec24f0 --- /dev/null +++ b/src/main/resources/fxml/MainWindow.fxml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bin/resources/Homeflix_Icon_64x64.png b/src/main/resources/icons/Homeflix_Icon_64x64.png similarity index 100% rename from bin/resources/Homeflix_Icon_64x64.png rename to src/main/resources/icons/Homeflix_Icon_64x64.png diff --git a/bin/resources/Homeflix_Poster.png b/src/main/resources/icons/Homeflix_Poster.png similarity index 100% rename from bin/resources/Homeflix_Poster.png rename to src/main/resources/icons/Homeflix_Poster.png diff --git a/bin/resources/icons/close_black_2048x2048.png b/src/main/resources/icons/close_black_2048x2048.png similarity index 100% rename from bin/resources/icons/close_black_2048x2048.png rename to src/main/resources/icons/close_black_2048x2048.png diff --git a/bin/resources/icons/ic_favorite_black_18dp_1x.png b/src/main/resources/icons/ic_favorite_black_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_favorite_black_18dp_1x.png rename to src/main/resources/icons/ic_favorite_black_18dp_1x.png diff --git a/bin/resources/icons/ic_favorite_border_black_18dp_1x.png b/src/main/resources/icons/ic_favorite_border_black_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_favorite_border_black_18dp_1x.png rename to src/main/resources/icons/ic_favorite_border_black_18dp_1x.png diff --git a/bin/resources/icons/ic_play_arrow_black_18dp_1x.png b/src/main/resources/icons/ic_play_arrow_black_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_play_arrow_black_18dp_1x.png rename to src/main/resources/icons/ic_play_arrow_black_18dp_1x.png diff --git a/bin/resources/icons/ic_play_arrow_white_18dp_1x.png b/src/main/resources/icons/ic_play_arrow_white_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_play_arrow_white_18dp_1x.png rename to src/main/resources/icons/ic_play_arrow_white_18dp_1x.png diff --git a/bin/resources/icons/ic_search_black_18dp_1x.png b/src/main/resources/icons/ic_search_black_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_search_black_18dp_1x.png rename to src/main/resources/icons/ic_search_black_18dp_1x.png diff --git a/bin/resources/icons/ic_skip_next_black_18dp_1x.png b/src/main/resources/icons/ic_skip_next_black_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_skip_next_black_18dp_1x.png rename to src/main/resources/icons/ic_skip_next_black_18dp_1x.png diff --git a/bin/resources/icons/ic_skip_next_white_18dp_1x.png b/src/main/resources/icons/ic_skip_next_white_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_skip_next_white_18dp_1x.png rename to src/main/resources/icons/ic_skip_next_white_18dp_1x.png diff --git a/bin/resources/icons/ic_skip_previous_black_18dp_1x.png b/src/main/resources/icons/ic_skip_previous_black_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_skip_previous_black_18dp_1x.png rename to src/main/resources/icons/ic_skip_previous_black_18dp_1x.png diff --git a/bin/resources/icons/ic_skip_previous_white_18dp_1x.png b/src/main/resources/icons/ic_skip_previous_white_18dp_1x.png similarity index 100% rename from bin/resources/icons/ic_skip_previous_white_18dp_1x.png rename to src/main/resources/icons/ic_skip_previous_white_18dp_1x.png diff --git a/bin/libraries/Licenses/Apache_License.txt b/src/main/resources/licenses/apache2.txt similarity index 99% rename from bin/libraries/Licenses/Apache_License.txt rename to src/main/resources/licenses/apache2.txt index d645695..d5cc580 100644 --- a/bin/libraries/Licenses/Apache_License.txt +++ b/src/main/resources/licenses/apache2.txt @@ -1,5 +1,4 @@ - - Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -187,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2014 JFoenix. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/main/resources/licenses/gnu_gpl3.txt b/src/main/resources/licenses/gnu_gpl3.txt new file mode 100644 index 0000000..d71976c --- /dev/null +++ b/src/main/resources/licenses/gnu_gpl3.txt @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/bin/libraries/Licenses/MIT_License.txt b/src/main/resources/licenses/mit.txt similarity index 98% rename from bin/libraries/Licenses/MIT_License.txt rename to src/main/resources/licenses/mit.txt index 5e83ac1..0b8017f 100644 --- a/bin/libraries/Licenses/MIT_License.txt +++ b/src/main/resources/licenses/mit.txt @@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/src/resources/HomeFlix-Local_de_DE.properties b/src/main/resources/locals/HomeFlix-Local_de_DE.properties similarity index 75% rename from src/resources/HomeFlix-Local_de_DE.properties rename to src/main/resources/locals/HomeFlix-Local_de_DE.properties index aa9c214..544d512 100644 --- a/src/resources/HomeFlix-Local_de_DE.properties +++ b/src/main/resources/locals/HomeFlix-Local_de_DE.properties @@ -8,26 +8,26 @@ tfSearch = Suche... openFolder = Ordner \u00F6ffnen #settings translations -settingsHead1Label = HomeFlix Einstellungen -tfPath = Pfad... -chooseFolder = Ordner ausw\u00E4hlen -mainColorLabel = Hauptfarbe: -fontsizeLabel = Schriftgr\u00F6\u00DFe: -localLabel = Sprache: +homeflixSettingsLbl = HomeFlix Einstellungen +filmDirTextField = Pfad... +addDirectory = Ordner hinzuf\u00FCgen +addStreamSource = Stream Quelle hinzuf\u00FCgen +mainColorLbl = Hauptfarbe: +fontsizeLbl = Schriftgr\u00F6\u00DFe: +languageLbl = Sprache: checkUpdates = Auf Update pr\u00FCfen -checkingUpdates = Es wird nach Updates gesucht... -updateBtnavail = Update verf\u00FCgbar -updateBtnNotavail = Kein Update verf\u00FCgbar -autoUpdateLabel = beim Start nach Updates suchen: -version = Version: +updateBtnChecking = Es wird nach Updates gesucht... +updateBtnUpdateAvailable = Update verf\u00FCgbar +updateBtnNoUpdateAvailable = Kein Update verf\u00FCgbar +autoUpdate = beim Start nach Updates suchen: +branchLbl = Updatezweig #column translations -columnName = Name -columnRating = Bewertung columnStreamUrl = Datei Name -columnResolution = Aufl\u00F6sung +columnName = Name columnSeason = Staffel -columnYear = Jahr +columnEpisode = Episode +columnFavorite = Favorit #error translations errorUpdateV = Beim ausf\u00FChren des Updates ist ein Fehler aufgetreten! \nError: could not check update version (nvc)\nWeitere Hilfe erhalten sie unter www.kellerkinder.xyz \noder wenden sie sich an support@kellerkinder.xyz @@ -39,7 +39,7 @@ errorLoad = Beim laden der Einstellungen ist ein Fehler aufgetreten! errorSave = Beim speichern der Einstellungen ist ein Fehler aufgetreten! noFilmFound = Kein Film mit diesem Titel gefunden! vlcNotInstalled = Um einen Film abspielen wird der VLC Media Player ben\u00F6tigt! -infoText = \nMaintainer: seilo@kellerkinder.xyz und \nhendrik.schutter@coptersicht.de \n(c) 2016-2017 Kellerkinder www.kellerkinder.xyz +infoText = \nAutoren: \n \u2022 seil0@kellerkinder.xyz \n \u2022 hendrik.schutter@coptersicht.de \n(c) 2016-2018 Kellerkinder www.kellerkinder.xyz #textFlow translations title = Titel diff --git a/src/resources/HomeFlix-Local_en_US.properties b/src/main/resources/locals/HomeFlix-Local_en_US.properties similarity index 74% rename from src/resources/HomeFlix-Local_en_US.properties rename to src/main/resources/locals/HomeFlix-Local_en_US.properties index d166f04..ce5f4af 100644 --- a/src/resources/HomeFlix-Local_en_US.properties +++ b/src/main/resources/locals/HomeFlix-Local_en_US.properties @@ -8,26 +8,26 @@ tfSearch = Search... openFolder = open Folder #settings translations -settingsHead1Label = HomeFlix Settings -tfPath = Path... -chooseFolder = choose Directory -mainColorLabel = main color: -fontsizeLabel = font size: -localLabel = local: +homeflixSettingsLbl = HomeFlix Settings +filmDirTextField = Path... +addDirectory = add directory +addStreamSource = add stream source +mainColorLbl = main color: +fontsizeLbl = font size: +languageLbl = local: checkUpdates = check for updates -checkingUpdates = checking for updates... -updateBtnavail = update available -updateBtnNotavail = no update available -autoUpdateLabel = check at startup for updates: -version = Version: +updateBtnChecking = checking for updates... +updateBtnUpdateAvailable = update available +updateBtnNoUpdateAvailable = no update available +autoUpdate = check at startup for updates: +branchLbl = Branch #column translations -columnName = Name -columnRating = Rating columnStreamUrl = File Name -columnResolution = Resolution +columnName = Name columnSeason = Season -columnYear = Year +columnEpisode = Episode +columnFavorite = Favorite #error translations errorUpdateV = An error has occurred during update! \nError: could not check update version (nvc) \nTo get help, visit www.kellerkinder.xyz \nor contcat support@kellerkinder.xyz @@ -39,7 +39,7 @@ errorLoad = An error occurred while loading the settings! errorSave = An error occurred while saving the settings! noFilmFound = No film with this title found! vlcNotInstalled = VLC Media Player is required to play a movie! -infoText = \nMaintainer: seilo@kellerkinder.xyz and \nhendrik.schutter@coptersicht.de \n(c) 2016-2017 Kellerkinder www.kellerkinder.xyz +infoText = \nMaintainers: \n \u2022 seil0@kellerkinder.xyz \n \u2022 hendrik.schutter@coptersicht.de \n(c) 2016-2018 Kellerkinder www.kellerkinder.xyz #textFlow translations title = Title diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..b3ad7b2 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources/Homeflix_Icon_64x64.png b/src/resources/Homeflix_Icon_64x64.png deleted file mode 100644 index 64787d6..0000000 Binary files a/src/resources/Homeflix_Icon_64x64.png and /dev/null differ diff --git a/src/resources/Homeflix_Poster.png b/src/resources/Homeflix_Poster.png deleted file mode 100644 index 9f2aa98..0000000 Binary files a/src/resources/Homeflix_Poster.png and /dev/null differ diff --git a/src/resources/icons/close_black_2048x2048.png b/src/resources/icons/close_black_2048x2048.png deleted file mode 100644 index 2d0397b..0000000 Binary files a/src/resources/icons/close_black_2048x2048.png and /dev/null differ diff --git a/src/resources/icons/ic_favorite_black_18dp_1x.png b/src/resources/icons/ic_favorite_black_18dp_1x.png deleted file mode 100644 index 69be1f5..0000000 Binary files a/src/resources/icons/ic_favorite_black_18dp_1x.png and /dev/null differ diff --git a/src/resources/icons/ic_favorite_border_black_18dp_1x.png b/src/resources/icons/ic_favorite_border_black_18dp_1x.png deleted file mode 100644 index 7edb675..0000000 Binary files a/src/resources/icons/ic_favorite_border_black_18dp_1x.png and /dev/null differ diff --git a/src/resources/icons/ic_play_arrow_black_18dp_1x.png b/src/resources/icons/ic_play_arrow_black_18dp_1x.png deleted file mode 100644 index 96021dc..0000000 Binary files a/src/resources/icons/ic_play_arrow_black_18dp_1x.png and /dev/null differ diff --git a/src/resources/icons/ic_play_arrow_white_18dp_1x.png b/src/resources/icons/ic_play_arrow_white_18dp_1x.png deleted file mode 100644 index cae85ab..0000000 Binary files a/src/resources/icons/ic_play_arrow_white_18dp_1x.png and /dev/null differ diff --git a/src/resources/icons/ic_search_black_18dp_1x.png b/src/resources/icons/ic_search_black_18dp_1x.png deleted file mode 100644 index f0d4e97..0000000 Binary files a/src/resources/icons/ic_search_black_18dp_1x.png and /dev/null differ diff --git a/src/resources/icons/ic_skip_next_black_18dp_1x.png b/src/resources/icons/ic_skip_next_black_18dp_1x.png deleted file mode 100644 index 327fd8d..0000000 Binary files a/src/resources/icons/ic_skip_next_black_18dp_1x.png and /dev/null differ diff --git a/src/resources/icons/ic_skip_next_white_18dp_1x.png b/src/resources/icons/ic_skip_next_white_18dp_1x.png deleted file mode 100644 index 26434a0..0000000 Binary files a/src/resources/icons/ic_skip_next_white_18dp_1x.png and /dev/null differ diff --git a/src/resources/icons/ic_skip_previous_black_18dp_1x.png b/src/resources/icons/ic_skip_previous_black_18dp_1x.png deleted file mode 100644 index 34c528d..0000000 Binary files a/src/resources/icons/ic_skip_previous_black_18dp_1x.png and /dev/null differ diff --git a/src/resources/icons/ic_skip_previous_white_18dp_1x.png b/src/resources/icons/ic_skip_previous_white_18dp_1x.png deleted file mode 100644 index e7d7643..0000000 Binary files a/src/resources/icons/ic_skip_previous_white_18dp_1x.png and /dev/null differ diff --git a/src/test/java/org/kellerkinder/Project_HomeFlix/AppTest.java b/src/test/java/org/kellerkinder/Project_HomeFlix/AppTest.java new file mode 100644 index 0000000..12afbc3 --- /dev/null +++ b/src/test/java/org/kellerkinder/Project_HomeFlix/AppTest.java @@ -0,0 +1,38 @@ +package org.kellerkinder.Project_HomeFlix; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/updates/ProjectHomeFlix.jar b/updates/ProjectHomeFlix.jar deleted file mode 100644 index 31122e3..0000000 Binary files a/updates/ProjectHomeFlix.jar and /dev/null differ diff --git a/updates/buildNumber.txt b/updates/buildNumber.txt deleted file mode 100644 index c75acbe..0000000 --- a/updates/buildNumber.txt +++ /dev/null @@ -1 +0,0 @@ -127 diff --git a/updates/downloadLink.txt b/updates/downloadLink.txt deleted file mode 100644 index 61d3ac5..0000000 --- a/updates/downloadLink.txt +++ /dev/null @@ -1 +0,0 @@ -https://raw.githubusercontent.com/Seil0/Project-HomeFlix/master/updates/ProjectHomeFlix.jar \ No newline at end of file diff --git a/updates/version.txt b/updates/version.txt deleted file mode 100644 index 1d0ba9e..0000000 --- a/updates/version.txt +++ /dev/null @@ -1 +0,0 @@ -0.4.0