wörk wörk (day 2)
This commit is contained in:
parent
2decbf015c
commit
ed51a990a9
16
pom.xml
16
pom.xml
@ -31,6 +31,11 @@
|
|||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
<version>2.6</version>
|
<version>2.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-codec</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
<version>1.14</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.formdev</groupId>
|
<groupId>com.formdev</groupId>
|
||||||
<artifactId>flatlaf</artifactId>
|
<artifactId>flatlaf</artifactId>
|
||||||
@ -47,15 +52,14 @@
|
|||||||
<version>0.5.4</version>
|
<version>0.5.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.takari.zsync</groupId>
|
<groupId>com.github.mfornos</groupId>
|
||||||
<artifactId>zsync-parent</artifactId>
|
<artifactId>humanize-slim</artifactId>
|
||||||
<version>0.1.0</version>
|
<version>1.2.2</version>
|
||||||
<type>pom</type>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.bitshifted</groupId>
|
<groupId>com.github.Gurkengewuerz</groupId>
|
||||||
<artifactId>zsyncer</artifactId>
|
<artifactId>zsyncer</artifactId>
|
||||||
<version>-f69d844481-1</version>
|
<version>locale_fix-2f7565d392-1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<xy x="20" y="20" width="1048" height="526"/>
|
<xy x="20" y="20" width="1048" height="556"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties/>
|
<properties/>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
@ -407,7 +407,7 @@
|
|||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
<grid id="3b45c" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="3b45c" layout-manager="GridLayoutManager" row-count="6" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="3" bottom="0" right="0"/>
|
<margin top="0" left="3" bottom="0" right="0"/>
|
||||||
<constraints border-constraint="Center"/>
|
<constraints border-constraint="Center"/>
|
||||||
<properties/>
|
<properties/>
|
||||||
@ -423,7 +423,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<hspacer id="f47e0">
|
<hspacer id="f47e0">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="2" row-span="1" col-span="2" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</hspacer>
|
</hspacer>
|
||||||
<component id="7b453" class="javax.swing.JLabel" binding="syncCheckStatusLabel">
|
<component id="7b453" class="javax.swing.JLabel" binding="syncCheckStatusLabel">
|
||||||
@ -437,7 +437,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<component id="c7b6" class="javax.swing.JProgressBar" binding="syncCheckProgress">
|
<component id="c7b6" class="javax.swing.JProgressBar" binding="syncCheckProgress">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="1" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<string value=""/>
|
<string value=""/>
|
||||||
@ -448,7 +448,7 @@
|
|||||||
<grid id="c1d6e" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="c1d6e" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
<grid row="2" column="0" row-span="1" col-span="4" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties/>
|
<properties/>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
@ -526,6 +526,23 @@
|
|||||||
<text value="0"/>
|
<text value="0"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
|
<component id="4c8b" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text resource-bundle="lang" key="changed_filesize"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="585a0" class="javax.swing.JLabel" binding="syncChangedFileSizeLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="0.0 B"/>
|
||||||
|
<toolTipText resource-bundle="lang" key="changed_filesize_tooltip"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
</children>
|
</children>
|
||||||
@ -573,22 +590,9 @@
|
|||||||
<text resource-bundle="lang" key="total_file_size"/>
|
<text resource-bundle="lang" key="total_file_size"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<vspacer id="54eb4">
|
|
||||||
<constraints>
|
|
||||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
</vspacer>
|
|
||||||
<component id="d85a8" class="javax.swing.JLabel">
|
|
||||||
<constraints>
|
|
||||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties>
|
|
||||||
<text resource-bundle="lang" key="downloaded"/>
|
|
||||||
</properties>
|
|
||||||
</component>
|
|
||||||
<component id="f5997" class="javax.swing.JLabel">
|
<component id="f5997" class="javax.swing.JLabel">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text resource-bundle="lang" key="speed"/>
|
<text resource-bundle="lang" key="speed"/>
|
||||||
@ -596,7 +600,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<component id="25551" class="javax.swing.JLabel">
|
<component id="25551" class="javax.swing.JLabel">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text resource-bundle="lang" key="remaining_time"/>
|
<text resource-bundle="lang" key="remaining_time"/>
|
||||||
@ -610,17 +614,9 @@
|
|||||||
<text value="0.0 B"/>
|
<text value="0.0 B"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="d9013" class="javax.swing.JLabel">
|
<component id="617c7" class="javax.swing.JLabel" binding="syncDownloadSpeedLabel">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
|
||||||
<properties>
|
|
||||||
<text value=""/>
|
|
||||||
</properties>
|
|
||||||
</component>
|
|
||||||
<component id="617c7" class="javax.swing.JLabel">
|
|
||||||
<constraints>
|
|
||||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text value=""/>
|
<text value=""/>
|
||||||
@ -628,7 +624,39 @@
|
|||||||
</component>
|
</component>
|
||||||
<component id="b64ac" class="javax.swing.JLabel">
|
<component id="b64ac" class="javax.swing.JLabel">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="d85a8" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text resource-bundle="lang" key="downloaded"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="d9013" class="javax.swing.JLabel" binding="syncDownloadedLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value=""/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="28be3" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text resource-bundle="lang" key="file_count"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="9148" class="javax.swing.JLabel" binding="syncFileCountLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text value=""/>
|
<text value=""/>
|
||||||
@ -671,24 +699,24 @@
|
|||||||
<properties/>
|
<properties/>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
<children>
|
<children>
|
||||||
<component id="f39cc" class="javax.swing.JProgressBar" binding="progressBar2" default-binding="true">
|
<component id="f39cc" class="javax.swing.JProgressBar" binding="syncDownloadProgress">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<string value=""/>
|
<string value=""/>
|
||||||
<stringPainted value="true"/>
|
<stringPainted value="true"/>
|
||||||
<value value="50"/>
|
<value value="0"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="87392" class="javax.swing.JProgressBar" binding="progressBar3" default-binding="true">
|
<component id="87392" class="javax.swing.JProgressBar" binding="syncFileProgress">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<string value=""/>
|
<string value=""/>
|
||||||
<stringPainted value="true"/>
|
<stringPainted value="true"/>
|
||||||
<value value="50"/>
|
<value value="0"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<grid id="99173" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="99173" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
|
@ -5,6 +5,7 @@ import de.mc8051.arma3launcher.model.JCheckBoxTree;
|
|||||||
import de.mc8051.arma3launcher.model.ModListRenderer;
|
import de.mc8051.arma3launcher.model.ModListRenderer;
|
||||||
import de.mc8051.arma3launcher.model.PresetListRenderer;
|
import de.mc8051.arma3launcher.model.PresetListRenderer;
|
||||||
import de.mc8051.arma3launcher.model.PresetTableModel;
|
import de.mc8051.arma3launcher.model.PresetTableModel;
|
||||||
|
import de.mc8051.arma3launcher.model.RepositoryTreeNode;
|
||||||
import de.mc8051.arma3launcher.model.ServerTableModel;
|
import de.mc8051.arma3launcher.model.ServerTableModel;
|
||||||
import de.mc8051.arma3launcher.objects.AbstractMod;
|
import de.mc8051.arma3launcher.objects.AbstractMod;
|
||||||
import de.mc8051.arma3launcher.objects.Mod;
|
import de.mc8051.arma3launcher.objects.Mod;
|
||||||
@ -13,9 +14,12 @@ import de.mc8051.arma3launcher.objects.Modset;
|
|||||||
import de.mc8051.arma3launcher.objects.Server;
|
import de.mc8051.arma3launcher.objects.Server;
|
||||||
import de.mc8051.arma3launcher.repo.FileChecker;
|
import de.mc8051.arma3launcher.repo.FileChecker;
|
||||||
import de.mc8051.arma3launcher.repo.RepositoryManger;
|
import de.mc8051.arma3launcher.repo.RepositoryManger;
|
||||||
|
import de.mc8051.arma3launcher.repo.SyncList;
|
||||||
|
import de.mc8051.arma3launcher.repo.Syncer;
|
||||||
import de.mc8051.arma3launcher.steam.SteamTimer;
|
import de.mc8051.arma3launcher.steam.SteamTimer;
|
||||||
import de.mc8051.arma3launcher.utils.Callback;
|
import de.mc8051.arma3launcher.utils.Callback;
|
||||||
import de.mc8051.arma3launcher.utils.LangUtils;
|
import de.mc8051.arma3launcher.utils.LangUtils;
|
||||||
|
import humanize.Humanize;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
@ -24,6 +28,7 @@ import javax.swing.plaf.basic.BasicTabbedPaneUI;
|
|||||||
import javax.swing.text.DefaultFormatter;
|
import javax.swing.text.DefaultFormatter;
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
import javax.swing.tree.DefaultTreeModel;
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
|
import javax.swing.tree.TreeNode;
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
@ -37,11 +42,6 @@ import java.net.URLDecoder;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@ -115,8 +115,8 @@ public class LauncherGUI implements Observer {
|
|||||||
private JProgressBar syncCheckProgress;
|
private JProgressBar syncCheckProgress;
|
||||||
private JButton syncCheckAbortButton;
|
private JButton syncCheckAbortButton;
|
||||||
private JButton syncCheckButton;
|
private JButton syncCheckButton;
|
||||||
private JProgressBar progressBar2;
|
public JProgressBar syncDownloadProgress;
|
||||||
private JProgressBar progressBar3;
|
public JProgressBar syncFileProgress;
|
||||||
private JButton syncDownloadButton;
|
private JButton syncDownloadButton;
|
||||||
private JButton syncDownloadAbortButton;
|
private JButton syncDownloadAbortButton;
|
||||||
private JButton syncPauseButton;
|
private JButton syncPauseButton;
|
||||||
@ -130,29 +130,33 @@ public class LauncherGUI implements Observer {
|
|||||||
private JLabel syncAddedFilesLabel;
|
private JLabel syncAddedFilesLabel;
|
||||||
private JLabel syncChangedFilesLabel;
|
private JLabel syncChangedFilesLabel;
|
||||||
private JLabel syncSizeLabel;
|
private JLabel syncSizeLabel;
|
||||||
|
private JLabel syncChangedFileSizeLabel;
|
||||||
|
private JLabel syncFileCountLabel;
|
||||||
|
public JLabel syncDownloadedLabel;
|
||||||
|
public JLabel syncDownloadSpeedLabel;
|
||||||
|
|
||||||
private JCheckBoxTree repoTree;
|
private JCheckBoxTree repoTree;
|
||||||
private FileChecker fileChecker;
|
private FileChecker fileChecker;
|
||||||
|
private Syncer syncer;
|
||||||
// TODO: Updater
|
private SyncList lastSynclist;
|
||||||
/*
|
|
||||||
Prüfung
|
|
||||||
In eine Liste hinzufügen wenn Datei in modset.json (Neu runterladen), nicht in modset.json (zum Löschen) oder die Größe unterschiedlich ist (Geändert)
|
|
||||||
Checkboxen beim Syncronisieren deaktivieren
|
|
||||||
*/
|
|
||||||
|
|
||||||
public LauncherGUI() {
|
public LauncherGUI() {
|
||||||
fileChecker = new FileChecker(syncCheckProgress);
|
fileChecker = new FileChecker(syncCheckProgress);
|
||||||
|
syncer = new Syncer(this);
|
||||||
|
|
||||||
RepositoryManger.getInstance().addObserver(this);
|
RepositoryManger.getInstance().addObserver(this);
|
||||||
SteamTimer.addObserver(this);
|
SteamTimer.addObserver(this);
|
||||||
fileChecker.addObserver(this);
|
fileChecker.addObserver(this);
|
||||||
|
syncer.addObserver(this);
|
||||||
|
|
||||||
updateTreePanel.remove(tree1);
|
updateTreePanel.remove(tree1);
|
||||||
|
|
||||||
repoTree = new JCheckBoxTree();
|
repoTree = new JCheckBoxTree();
|
||||||
updateTreePanel.add(repoTree, BorderLayout.CENTER);
|
updateTreePanel.add(repoTree, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
DefaultTreeModel model = (DefaultTreeModel) repoTree.getModel();
|
||||||
|
model.setRoot(new RepositoryTreeNode("Repository"));
|
||||||
|
|
||||||
updateTreePanel.revalidate();
|
updateTreePanel.revalidate();
|
||||||
updateTreePanel.repaint();
|
updateTreePanel.repaint();
|
||||||
|
|
||||||
@ -221,7 +225,6 @@ public class LauncherGUI implements Observer {
|
|||||||
if (!e.getValueIsAdjusting()) {
|
if (!e.getValueIsAdjusting()) {
|
||||||
PresetTableModel m = (PresetTableModel) presetList.getModel();
|
PresetTableModel m = (PresetTableModel) presetList.getModel();
|
||||||
Modset modset = (Modset) m.getElementAt(presetList.getSelectedIndex());
|
Modset modset = (Modset) m.getElementAt(presetList.getSelectedIndex());
|
||||||
System.out.println(modset.getName());
|
|
||||||
|
|
||||||
if (modset.getType() == Modset.Type.SERVER) {
|
if (modset.getType() == Modset.Type.SERVER) {
|
||||||
renamePresetButton.setEnabled(false);
|
renamePresetButton.setEnabled(false);
|
||||||
@ -283,6 +286,11 @@ public class LauncherGUI implements Observer {
|
|||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
RepositoryManger.getInstance().refreshMeta();
|
RepositoryManger.getInstance().refreshMeta();
|
||||||
|
try {
|
||||||
|
Thread.sleep(750);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
RepositoryManger.getInstance().refreshModset();
|
RepositoryManger.getInstance().refreshModset();
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
@ -294,7 +302,8 @@ public class LauncherGUI implements Observer {
|
|||||||
syncCheckStatusLabel.setText("Running!");
|
syncCheckStatusLabel.setText("Running!");
|
||||||
new Thread(() -> fileChecker.check()).start();
|
new Thread(() -> fileChecker.check()).start();
|
||||||
|
|
||||||
// TODO: disable JTree Checkboxes
|
repoTree.setCheckboxesEnabled(false);
|
||||||
|
repoTree.setCheckboxesChecked(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -304,6 +313,28 @@ public class LauncherGUI implements Observer {
|
|||||||
fileChecker.stop();
|
fileChecker.stop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
syncDownloadButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
new Thread(() -> syncer.sync(lastSynclist.clone())).start();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
syncDownloadAbortButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
syncer.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
syncPauseButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
syncer.setPaused(!syncer.isPaused());
|
||||||
|
syncPauseButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void infoBox(String infoMessage, String titleBar) {
|
public static void infoBox(String infoMessage, String titleBar) {
|
||||||
@ -550,78 +581,54 @@ public class LauncherGUI implements Observer {
|
|||||||
spinner.addChangeListener(new SettingsHandler.SpinnerListener(paraObj));
|
spinner.addChangeListener(new SettingsHandler.SpinnerListener(paraObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<AbstractMod> getSyncList() {
|
public SyncList getSyncList() {
|
||||||
ArrayList<AbstractMod> modList = new ArrayList<>();
|
SyncList synclist = new SyncList();
|
||||||
|
|
||||||
HashMap<String, ArrayList<String>> tempMap = new HashMap<>();
|
DefaultTreeModel model = (DefaultTreeModel) repoTree.getModel();
|
||||||
for (TreePath checkedPath : repoTree.getCheckedPaths()) {
|
RepositoryTreeNode root = (RepositoryTreeNode) model.getRoot();
|
||||||
DefaultMutableTreeNode tn = (DefaultMutableTreeNode)checkedPath.getLastPathComponent();
|
for (TreeNode leaf : root.getAllLeafNodes()) {
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) leaf;
|
||||||
|
TreeNode[] path = node.getPath();
|
||||||
|
boolean isSelected = repoTree.isSelected(new TreePath(path));
|
||||||
|
if (!isSelected) continue;
|
||||||
|
|
||||||
if(tn.getChildCount() > 0) continue;
|
ArrayList<String> treePathList = new ArrayList<>();
|
||||||
Object[] path = checkedPath.getPath();
|
for (int i = 2; i < path.length; i++) {
|
||||||
DefaultMutableTreeNode[] modifiedArray = Arrays.stream(Arrays.copyOfRange(path, 1, path.length)).toArray(DefaultMutableTreeNode[]::new);
|
treePathList.add(String.valueOf(((DefaultMutableTreeNode) path[i]).getUserObject()));
|
||||||
|
|
||||||
ArrayList<String> strings = new ArrayList<>();
|
|
||||||
if(tempMap.containsKey(String.valueOf(modifiedArray[0].getUserObject()))) {
|
|
||||||
strings = tempMap.get(String.valueOf(modifiedArray[0].getUserObject()));
|
|
||||||
}
|
}
|
||||||
|
String treePath = String.join("/", treePathList);
|
||||||
|
String modname = String.valueOf(((DefaultMutableTreeNode) path[1]).getUserObject());
|
||||||
|
|
||||||
String modPath = "";
|
if (fileChecker.getChanged().containsKey(modname)) {
|
||||||
for (int i = 1; i < modifiedArray.length; i++) {
|
for (ModFile modFile : fileChecker.getChanged().get(modname)) {
|
||||||
modPath += String.valueOf(modifiedArray[i].getUserObject()) + "/";
|
if (String.join("/", modFile.getPath()).equals(treePath)) {
|
||||||
}
|
synclist.add(modFile);
|
||||||
modPath = modPath.isEmpty() ? "" : modPath.substring(0, modPath.length() - 1);
|
|
||||||
strings.add(modPath);
|
|
||||||
|
|
||||||
tempMap.put((String) modifiedArray[0].getUserObject(), strings);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<String, ArrayList<String>> entry : tempMap.entrySet()) {
|
|
||||||
String modS = entry.getKey();
|
|
||||||
ArrayList<String> modlistS = entry.getValue();
|
|
||||||
|
|
||||||
if(modlistS.isEmpty()) {
|
|
||||||
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
|
||||||
if (abstractMod.getName().equals(modS)) {
|
|
||||||
modList.add(abstractMod);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
|
||||||
if (abstractMod.getName().equals(modS)) {
|
|
||||||
if(!(abstractMod instanceof Mod)) continue;
|
|
||||||
Mod m = ((Mod) abstractMod).clone();
|
|
||||||
|
|
||||||
for (int i = 0; i < m.getFiles().size(); i++) {
|
|
||||||
boolean found = false;
|
|
||||||
for (String pathS : modlistS) {
|
|
||||||
if(m.getFiles().get(i).getModfileString().equals(pathS)) {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found) {
|
if (fileChecker.getAdded().containsKey(modname)) {
|
||||||
m.getFiles().remove(i);
|
for (ModFile modFile : fileChecker.getAdded().get(modname)) {
|
||||||
|
if (String.join("/", modFile.getPath()).equals(treePath)) {
|
||||||
|
synclist.add(modFile);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
synclist.setDeleted(fileChecker.getDeleted());
|
||||||
|
|
||||||
modList.add(m);
|
return synclist;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateModList(Modset modset) {
|
public void updateModList(Modset modset) {
|
||||||
ListModel<String> model = (ListModel) modList.getModel();
|
ListModel<String> model = (ListModel) modList.getModel();
|
||||||
// TODO: Show All Mods (keyname)
|
// TODO: Show All Mods (keyname)
|
||||||
// TODO: Show not installed Mods with red font
|
// Show not installed Mods with red font
|
||||||
// TODO: Select Mod if in modset.Mods
|
// Select Mod if in modset.Mods
|
||||||
// TODO: Custom Checkbox Render
|
// Custom Checkbox Render
|
||||||
// TODO: Wenn modset.type == Server alle Checkboxen deaktivieren!
|
// Wenn modset.type == Server alle Checkboxen deaktivieren!
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRepoTree() {
|
public void updateRepoTree() {
|
||||||
@ -629,28 +636,26 @@ public class LauncherGUI implements Observer {
|
|||||||
collapseAllButton.setEnabled(false);
|
collapseAllButton.setEnabled(false);
|
||||||
|
|
||||||
DefaultTreeModel model = (DefaultTreeModel) repoTree.getModel();
|
DefaultTreeModel model = (DefaultTreeModel) repoTree.getModel();
|
||||||
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
|
RepositoryTreeNode root = (RepositoryTreeNode) model.getRoot();
|
||||||
root.setUserObject("Repository");
|
|
||||||
root.removeAllChildren();
|
root.removeAllChildren();
|
||||||
|
|
||||||
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
||||||
if (abstractMod instanceof Mod) {
|
if (abstractMod instanceof Mod) {
|
||||||
// Whole Folder
|
// Whole Folder
|
||||||
// TODO: Recursives Ordner Parsen und einzelne Treenodes erstellen
|
|
||||||
Mod m = (Mod) abstractMod;
|
Mod m = (Mod) abstractMod;
|
||||||
DefaultMutableTreeNode modFolder = new DefaultMutableTreeNode(m.getName(), true);
|
RepositoryTreeNode modFolder = new RepositoryTreeNode(m.getName(), true);
|
||||||
model.insertNodeInto(modFolder, root, root.getChildCount());
|
model.insertNodeInto(modFolder, root, root.getChildCount());
|
||||||
|
|
||||||
for (ModFile modfile : m.getFiles()) {
|
for (ModFile modfile : m.getFiles()) {
|
||||||
|
|
||||||
DefaultMutableTreeNode lastNode = modFolder;
|
RepositoryTreeNode lastNode = modFolder;
|
||||||
ArrayList<String> path = modfile.getPath();
|
ArrayList<String> path = modfile.getPath();
|
||||||
|
|
||||||
for (int i = 0; i < path.size(); i++) {
|
for (int i = 0; i < path.size() -1; i++) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
|
||||||
for (int j = 0; j < lastNode.getChildCount(); j++) {
|
for (int j = 0; j < lastNode.getChildCount(); j++) {
|
||||||
DefaultMutableTreeNode temp = (DefaultMutableTreeNode) lastNode.getChildAt(j);
|
RepositoryTreeNode temp = (RepositoryTreeNode) lastNode.getChildAt(j);
|
||||||
if (temp.getUserObject().equals(path.get(i))) {
|
if (temp.getUserObject().equals(path.get(i))) {
|
||||||
found = true;
|
found = true;
|
||||||
lastNode = temp;
|
lastNode = temp;
|
||||||
@ -659,26 +664,25 @@ public class LauncherGUI implements Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
DefaultMutableTreeNode temp = new DefaultMutableTreeNode(path.get(i));
|
RepositoryTreeNode temp = new RepositoryTreeNode(path.get(i));
|
||||||
model.insertNodeInto(temp, lastNode, lastNode.getChildCount());
|
model.insertNodeInto(temp, lastNode, lastNode.getChildCount());
|
||||||
lastNode = temp;
|
lastNode = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
model.insertNodeInto(new RepositoryTreeNode(modfile.getName(), getNodeColor(m.getName(), modfile)), lastNode, lastNode.getChildCount());
|
||||||
model.insertNodeInto(new DefaultMutableTreeNode(modfile.getName()), lastNode, lastNode.getChildCount());
|
|
||||||
}
|
}
|
||||||
sort(modFolder);
|
sort(modFolder);
|
||||||
} else if (abstractMod instanceof ModFile) {
|
} else if (abstractMod instanceof ModFile) {
|
||||||
// Just a Single FIle
|
// Just a Single FIle
|
||||||
ModFile m = (ModFile) abstractMod;
|
ModFile m = (ModFile) abstractMod;
|
||||||
model.insertNodeInto(new DefaultMutableTreeNode(m.getName(), false), root, root.getChildCount());
|
model.insertNodeInto(new RepositoryTreeNode(m.getName(), getNodeColor(m.getName(), m), false), root, root.getChildCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort(root);
|
sort(root);
|
||||||
|
setParentColor(root);
|
||||||
|
|
||||||
repoTree.clearCheckChangeEventListeners();
|
repoTree.clearCheckChangeEventListeners();
|
||||||
|
|
||||||
repoTree.resetCheckingState();
|
repoTree.resetCheckingState();
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
@ -690,19 +694,71 @@ public class LauncherGUI implements Observer {
|
|||||||
updateTreePanel.repaint();
|
updateTreePanel.repaint();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
repoTree.addCheckChangeEventListener(new JCheckBoxTree.CheckChangeEventListener() {
|
||||||
|
@Override
|
||||||
|
public void checkStateChanged(JCheckBoxTree.CheckChangeEvent event) {
|
||||||
|
lastSynclist = getSyncList();
|
||||||
|
if (lastSynclist.getSize() != 0)
|
||||||
|
syncSizeLabel.setText(Humanize.binaryPrefix(lastSynclist.getSize()));
|
||||||
|
else syncSizeLabel.setText("0.0 B");
|
||||||
|
if (lastSynclist.getCount() != 0) {
|
||||||
|
syncDownloadButton.setEnabled(true);
|
||||||
|
syncFileCountLabel.setText("" + lastSynclist.getCount());
|
||||||
|
} else {
|
||||||
|
syncDownloadButton.setEnabled(false);
|
||||||
|
syncFileCountLabel.setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
expandAllButton.setEnabled(true);
|
expandAllButton.setEnabled(true);
|
||||||
collapseAllButton.setEnabled(true);
|
collapseAllButton.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultMutableTreeNode sort(DefaultMutableTreeNode node) {
|
public Color getNodeColor(String mod, ModFile mf) {
|
||||||
|
if (fileChecker.getAdded().containsKey(mod)) {
|
||||||
|
ArrayList<ModFile> mfList = fileChecker.getAdded().get(mod);
|
||||||
|
for (ModFile modFile : mfList) {
|
||||||
|
if (modFile.getLocaleFile().getPath().equals(mf.getLocaleFile().getPath())) return Color.RED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileChecker.getChanged().containsKey(mod)) {
|
||||||
|
ArrayList<ModFile> mfList = fileChecker.getChanged().get(mod);
|
||||||
|
for (ModFile modFile : mfList) {
|
||||||
|
if (modFile.getLocaleFile().getPath().equals(mf.getLocaleFile().getPath())) return Color.ORANGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentColor(RepositoryTreeNode node) {
|
||||||
|
for (TreeNode leaf : node.getAllLeafNodes()) {
|
||||||
|
if (!(leaf instanceof RepositoryTreeNode)) continue;
|
||||||
|
RepositoryTreeNode mLeaf = (RepositoryTreeNode) leaf;
|
||||||
|
TreeNode[] path = mLeaf.getPath();
|
||||||
|
|
||||||
|
if (mLeaf.getLabelColor() == null) continue;
|
||||||
|
for (int i = 0; i < path.length - 1; i++) {
|
||||||
|
if (!(path[i] instanceof RepositoryTreeNode)) continue;
|
||||||
|
RepositoryTreeNode parent = (RepositoryTreeNode) path[i];
|
||||||
|
if (parent.getLabelColor() == mLeaf.getLabelColor()) continue;
|
||||||
|
if (parent.getLabelColor() == Color.RED) continue;
|
||||||
|
parent.setLabelColor(mLeaf.getLabelColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepositoryTreeNode sort(RepositoryTreeNode node) {
|
||||||
|
|
||||||
//sort alphabetically
|
//sort alphabetically
|
||||||
for (int i = 0; i < node.getChildCount() - 1; i++) {
|
for (int i = 0; i < node.getChildCount() - 1; i++) {
|
||||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
|
RepositoryTreeNode child = (RepositoryTreeNode) node.getChildAt(i);
|
||||||
String nt = child.getUserObject().toString();
|
String nt = child.getUserObject().toString();
|
||||||
|
|
||||||
for (int j = i + 1; j <= node.getChildCount() - 1; j++) {
|
for (int j = i + 1; j <= node.getChildCount() - 1; j++) {
|
||||||
DefaultMutableTreeNode prevNode = (DefaultMutableTreeNode) node.getChildAt(j);
|
RepositoryTreeNode prevNode = (RepositoryTreeNode) node.getChildAt(j);
|
||||||
String np = prevNode.getUserObject().toString();
|
String np = prevNode.getUserObject().toString();
|
||||||
|
|
||||||
if (nt.compareToIgnoreCase(np) > 0) {
|
if (nt.compareToIgnoreCase(np) > 0) {
|
||||||
@ -717,9 +773,9 @@ public class LauncherGUI implements Observer {
|
|||||||
|
|
||||||
//put folders first - normal on Windows and some flavors of Linux but not on Mac OS X.
|
//put folders first - normal on Windows and some flavors of Linux but not on Mac OS X.
|
||||||
for (int i = 0; i < node.getChildCount() - 1; i++) {
|
for (int i = 0; i < node.getChildCount() - 1; i++) {
|
||||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
|
RepositoryTreeNode child = (RepositoryTreeNode) node.getChildAt(i);
|
||||||
for (int j = i + 1; j <= node.getChildCount() - 1; j++) {
|
for (int j = i + 1; j <= node.getChildCount() - 1; j++) {
|
||||||
DefaultMutableTreeNode prevNode = (DefaultMutableTreeNode) node.getChildAt(j);
|
RepositoryTreeNode prevNode = (RepositoryTreeNode) node.getChildAt(j);
|
||||||
|
|
||||||
if (!prevNode.isLeaf() && child.isLeaf()) {
|
if (!prevNode.isLeaf() && child.isLeaf()) {
|
||||||
node.insert(child, j);
|
node.insert(child, j);
|
||||||
@ -783,25 +839,50 @@ public class LauncherGUI implements Observer {
|
|||||||
syncCheckAbortButton.setEnabled(false);
|
syncCheckAbortButton.setEnabled(false);
|
||||||
syncCheckStatusLabel.setText("Finished!");
|
syncCheckStatusLabel.setText("Finished!");
|
||||||
updateRepoTree();
|
updateRepoTree();
|
||||||
// TODO: Label einfärben
|
|
||||||
// TODO: Enable Tree Checkboxes
|
repoTree.setCheckboxesEnabled(true);
|
||||||
syncDownloadButton.setEnabled(true);
|
syncDownloadButton.setEnabled(true);
|
||||||
syncAddedFilesLabel.setText(String.valueOf(fileChecker.getAddedCount()));
|
syncAddedFilesLabel.setText(String.valueOf(fileChecker.getAddedCount()));
|
||||||
syncChangedFilesLabel.setText(String.valueOf(fileChecker.getChangedCount()));
|
syncChangedFilesLabel.setText(String.valueOf(fileChecker.getChangedCount()));
|
||||||
syncDeletedFilesLabel.setText(String.valueOf(fileChecker.getDeletedCount()));
|
syncDeletedFilesLabel.setText(String.valueOf(fileChecker.getDeletedCount()));
|
||||||
|
|
||||||
syncSizeLabel.setText(String.valueOf(fileChecker.getSize())); // TODO: Make Humanreadable
|
syncDownloadAbortButton.setEnabled(false);
|
||||||
|
syncDownloadButton.setEnabled(true);
|
||||||
|
syncPauseButton.setEnabled(false);
|
||||||
|
|
||||||
|
syncChangedFileSizeLabel.setText(Humanize.binaryPrefix(fileChecker.getSize()));
|
||||||
} else if (s.equals("fileCheckerStopped")) {
|
} else if (s.equals("fileCheckerStopped")) {
|
||||||
syncCheckButton.setEnabled(true);
|
syncCheckButton.setEnabled(true);
|
||||||
syncCheckAbortButton.setEnabled(false);
|
syncCheckAbortButton.setEnabled(false);
|
||||||
syncCheckProgress.setValue(0);
|
syncCheckProgress.setValue(0);
|
||||||
syncCheckStatusLabel.setText("Failed!");
|
syncCheckStatusLabel.setText("Failed!");
|
||||||
|
repoTree.setCheckboxesEnabled(false);
|
||||||
|
|
||||||
|
syncDownloadAbortButton.setEnabled(false);
|
||||||
|
syncDownloadButton.setEnabled(false);
|
||||||
|
syncPauseButton.setEnabled(false);
|
||||||
|
|
||||||
|
repoTree.setCheckboxesChecked(false);
|
||||||
|
|
||||||
syncAddedFilesLabel.setText("" + 0);
|
syncAddedFilesLabel.setText("" + 0);
|
||||||
syncChangedFilesLabel.setText("" + 0);
|
syncChangedFilesLabel.setText("" + 0);
|
||||||
syncDeletedFilesLabel.setText("" + 0);
|
syncDeletedFilesLabel.setText("" + 0);
|
||||||
|
|
||||||
syncSizeLabel.setText("0.0 B");
|
syncChangedFileSizeLabel.setText("0.0 B");
|
||||||
|
} else if (s.equals("syncStopped")) {
|
||||||
|
new Thread(() -> fileChecker.check()).start();
|
||||||
|
} else if (s.equals("syncComplete")) {
|
||||||
|
new Thread(() -> fileChecker.check()).start();
|
||||||
|
} else if (s.equals("syncContinue")) {
|
||||||
|
syncDownloadAbortButton.setEnabled(true);
|
||||||
|
syncPauseButton.setEnabled(true);
|
||||||
|
syncPauseButton.setText(LangUtils.getInstance().getString("pause"));
|
||||||
|
syncDownloadButton.setEnabled(false);
|
||||||
|
} else if (s.equals("syncPaused")) {
|
||||||
|
syncDownloadAbortButton.setEnabled(true);
|
||||||
|
syncPauseButton.setEnabled(true);
|
||||||
|
syncPauseButton.setText(LangUtils.getInstance().getString("resume"));
|
||||||
|
syncDownloadButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import java.util.EventListener;
|
|||||||
import java.util.EventObject;
|
import java.util.EventObject;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by SomethingSomething https://stackoverflow.com/a/21851201/5605489
|
* Created by SomethingSomething https://stackoverflow.com/a/21851201/5605489
|
||||||
@ -31,6 +32,7 @@ public class JCheckBoxTree extends JTree {
|
|||||||
// Defining data structure that will enable to fast check-indicate the state of each node
|
// Defining data structure that will enable to fast check-indicate the state of each node
|
||||||
// It totally replaces the "selection" mechanism of the JTree
|
// It totally replaces the "selection" mechanism of the JTree
|
||||||
private class CheckedNode {
|
private class CheckedNode {
|
||||||
|
boolean isEnabled;
|
||||||
boolean isSelected;
|
boolean isSelected;
|
||||||
boolean hasChildren;
|
boolean hasChildren;
|
||||||
boolean allChildrenSelected;
|
boolean allChildrenSelected;
|
||||||
@ -38,6 +40,7 @@ public class JCheckBoxTree extends JTree {
|
|||||||
public CheckedNode(boolean isSelected_, boolean hasChildren_, boolean allChildrenSelected_) {
|
public CheckedNode(boolean isSelected_, boolean hasChildren_, boolean allChildrenSelected_) {
|
||||||
isSelected = isSelected_;
|
isSelected = isSelected_;
|
||||||
hasChildren = hasChildren_;
|
hasChildren = hasChildren_;
|
||||||
|
isEnabled = true;
|
||||||
allChildrenSelected = allChildrenSelected_;
|
allChildrenSelected = allChildrenSelected_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,6 +110,11 @@ public class JCheckBoxTree extends JTree {
|
|||||||
return cn.isSelected && cn.hasChildren && !cn.allChildrenSelected;
|
return cn.isSelected && cn.hasChildren && !cn.allChildrenSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSelected(TreePath path) {
|
||||||
|
CheckedNode cn = nodesCheckingState.get(path);
|
||||||
|
return cn.isSelected;
|
||||||
|
}
|
||||||
|
|
||||||
public void resetCheckingState() {
|
public void resetCheckingState() {
|
||||||
nodesCheckingState = new HashMap<TreePath, CheckedNode>();
|
nodesCheckingState = new HashMap<TreePath, CheckedNode>();
|
||||||
checkedPaths = new HashSet<TreePath>();
|
checkedPaths = new HashSet<TreePath>();
|
||||||
@ -148,12 +156,21 @@ public class JCheckBoxTree extends JTree {
|
|||||||
boolean hasFocus) {
|
boolean hasFocus) {
|
||||||
checkBox.setText(value.toString());
|
checkBox.setText(value.toString());
|
||||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
|
||||||
|
|
||||||
|
if (node instanceof RepositoryTreeNode && ((RepositoryTreeNode) node).getLabelColor() != null) {
|
||||||
|
checkBox.setForeground(((RepositoryTreeNode) node).getLabelColor());
|
||||||
|
} else {
|
||||||
|
checkBox.setForeground(UIManager.getColor("CheckBox.foreground"));
|
||||||
|
}
|
||||||
|
|
||||||
TreePath tp = new TreePath(node.getPath());
|
TreePath tp = new TreePath(node.getPath());
|
||||||
CheckedNode cn = nodesCheckingState.get(tp);
|
CheckedNode cn = nodesCheckingState.get(tp);
|
||||||
if (cn == null) {
|
if (cn == null) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkBox.setSelected(cn.isSelected);
|
checkBox.setSelected(cn.isSelected);
|
||||||
|
checkBox.setEnabled(cn.isEnabled);
|
||||||
checkBox.setOpaque(cn.isSelected && cn.hasChildren && !cn.allChildrenSelected);
|
checkBox.setOpaque(cn.isSelected && cn.hasChildren && !cn.allChildrenSelected);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -264,6 +281,26 @@ public class JCheckBoxTree extends JTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCheckboxesChecked(boolean state) {
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) getModel().getRoot();
|
||||||
|
checkSubTree(new TreePath(node.getPath()), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheckboxesEnabled(TreePath tp, boolean state) {
|
||||||
|
CheckedNode cn = nodesCheckingState.get(tp);
|
||||||
|
cn.isEnabled = state;
|
||||||
|
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tp.getLastPathComponent();
|
||||||
|
for (int i = 0; i < node.getChildCount(); i++) {
|
||||||
|
setCheckboxesEnabled(tp.pathByAddingChild(node.getChildAt(i)), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheckboxesEnabled(boolean state) {
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) getModel().getRoot();
|
||||||
|
setCheckboxesEnabled(new TreePath(node.getPath()), state);
|
||||||
|
}
|
||||||
|
|
||||||
public void expandAllNodes() {
|
public void expandAllNodes() {
|
||||||
setTreeExpandedState(true);
|
setTreeExpandedState(true);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
package de.mc8051.arma3launcher.model;
|
||||||
|
|
||||||
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
import javax.swing.tree.TreeNode;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by gurkengewuerz.de on 26.03.2020.
|
||||||
|
*/
|
||||||
|
public class RepositoryTreeNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
|
private Color labelColor = null;
|
||||||
|
|
||||||
|
public RepositoryTreeNode(String userObject, boolean allowChildren) {
|
||||||
|
super(userObject, allowChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepositoryTreeNode(String userObject, Color labelColor, boolean allowChildren) {
|
||||||
|
super(userObject, allowChildren);
|
||||||
|
this.labelColor = labelColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepositoryTreeNode(String userObject, Color labelColor) {
|
||||||
|
super(userObject);
|
||||||
|
this.labelColor = labelColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepositoryTreeNode(String userObject) {
|
||||||
|
super(userObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getLabelColor() {
|
||||||
|
return labelColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLabelColor(Color labelColor) {
|
||||||
|
this.labelColor = labelColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<TreeNode> getAllLeafNodes() {
|
||||||
|
Set<TreeNode> leafNodes = new HashSet<>();
|
||||||
|
if (this.children == null) {
|
||||||
|
leafNodes.add(this);
|
||||||
|
} else {
|
||||||
|
for (Object child : this.children) {
|
||||||
|
if (child instanceof RepositoryTreeNode)
|
||||||
|
leafNodes.addAll(((RepositoryTreeNode) child).getAllLeafNodes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return leafNodes;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,19 @@
|
|||||||
package de.mc8051.arma3launcher.objects;
|
package de.mc8051.arma3launcher.objects;
|
||||||
|
|
||||||
|
import de.mc8051.arma3launcher.ArmA3Launcher;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by gurkengewuerz.de on 25.03.2020.
|
* Created by gurkengewuerz.de on 25.03.2020.
|
||||||
@ -17,8 +26,11 @@ public class ModFile implements AbstractMod {
|
|||||||
private String filename;
|
private String filename;
|
||||||
private String extension;
|
private String extension;
|
||||||
private String modfileString;
|
private String modfileString;
|
||||||
|
private String sha1sum;
|
||||||
|
private String parent;
|
||||||
|
private String localGeneratedSHA1sum = "";
|
||||||
|
|
||||||
public ModFile(File f, String modfile, long size) {
|
public ModFile(File f, String modfile, String parent, long size, String sha1sum) {
|
||||||
// File: Abosolut Path
|
// File: Abosolut Path
|
||||||
// modfile: addons/config/something.pbo
|
// modfile: addons/config/something.pbo
|
||||||
// size: size as in metafile on server
|
// size: size as in metafile on server
|
||||||
@ -28,6 +40,12 @@ public class ModFile implements AbstractMod {
|
|||||||
this.filename = FilenameUtils.getBaseName(modfile);
|
this.filename = FilenameUtils.getBaseName(modfile);
|
||||||
this.extension = FilenameUtils.getExtension(modfile);
|
this.extension = FilenameUtils.getExtension(modfile);
|
||||||
this.modfileString = modfile;
|
this.modfileString = modfile;
|
||||||
|
this.sha1sum = sha1sum.toLowerCase();
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModFile(File f, String modfile, long size, String sha1sum) {
|
||||||
|
this(f, modfile, null, size, sha1sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSize() {
|
public long getSize() {
|
||||||
@ -49,11 +67,11 @@ public class ModFile implements AbstractMod {
|
|||||||
public ArrayList<String> getPath() {
|
public ArrayList<String> getPath() {
|
||||||
ArrayList<String> list = new ArrayList<>();
|
ArrayList<String> list = new ArrayList<>();
|
||||||
File relativePath = new File("./" + modfileString);
|
File relativePath = new File("./" + modfileString);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
list.add(relativePath.getName());
|
list.add(relativePath.getName());
|
||||||
relativePath = relativePath.getParentFile();
|
relativePath = relativePath.getParentFile();
|
||||||
} while (relativePath.getParentFile() != null);
|
} while (relativePath.getParentFile() != null);
|
||||||
list.remove(0);
|
|
||||||
Collections.reverse(list);
|
Collections.reverse(list);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@ -79,4 +97,45 @@ public class ModFile implements AbstractMod {
|
|||||||
public File getLocaleFile() {
|
public File getLocaleFile() {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSHA1Sum() {
|
||||||
|
return sha1sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocalGeneratedSHA1Sum() {
|
||||||
|
try {
|
||||||
|
if (localGeneratedSHA1sum.isEmpty() && exists()) {
|
||||||
|
localGeneratedSHA1sum = DigestUtils.sha1Hex(new FileInputStream(f.getAbsolutePath())).toLowerCase();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
return localGeneratedSHA1sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemoteFile() {
|
||||||
|
String s = ArmA3Launcher.config.getString("sync.url");
|
||||||
|
if (parent == null || parent.isEmpty()) {
|
||||||
|
return s + "/" + encodeToURL(getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
s += "/" + encodeToURL(parent);
|
||||||
|
for (String seg : getPath()) {
|
||||||
|
s += "/" + encodeToURL(seg);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String encodeToURL(String s) {
|
||||||
|
try {
|
||||||
|
return URLEncoder.encode(s, StandardCharsets.UTF_8.name()).replace("+", "%20").replace("@", "%40");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
package de.mc8051.arma3launcher.repo;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by gurkengewuerz.de on 24.03.2020.
|
|
||||||
*/
|
|
||||||
public class DownloadThread implements Runnable {
|
|
||||||
|
|
||||||
private ProcessBuilder processBuilder;
|
|
||||||
private Process process;
|
|
||||||
private Thread thread;
|
|
||||||
|
|
||||||
private Status status = Status.PENDING;
|
|
||||||
|
|
||||||
public DownloadThread(ProcessBuilder processBuilder) {
|
|
||||||
this.processBuilder = processBuilder;
|
|
||||||
this.processBuilder.redirectErrorStream(true);
|
|
||||||
|
|
||||||
thread = new Thread(this);
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
process.destroy();
|
|
||||||
thread.interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Status getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
process = processBuilder.start();
|
|
||||||
status = Status.RUNNING;
|
|
||||||
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
String line;
|
|
||||||
while ( (line = reader.readLine()) != null && !thread.isInterrupted()) {
|
|
||||||
System.out.println(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
int exitVal = process.waitFor();
|
|
||||||
if(exitVal == 0) status = Status.FINNISHED;
|
|
||||||
else status = Status.ERROR;
|
|
||||||
|
|
||||||
System.out.println(exitVal);
|
|
||||||
} catch (IOException | InterruptedException ex) {
|
|
||||||
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
|
|
||||||
status = Status.ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Status {
|
|
||||||
PENDING(0),
|
|
||||||
RUNNING(1),
|
|
||||||
FINNISHED(2),
|
|
||||||
ERROR(3);
|
|
||||||
|
|
||||||
Status(int i) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,10 +30,10 @@ public class FileChecker implements Observable {
|
|||||||
private JProgressBar pb;
|
private JProgressBar pb;
|
||||||
private boolean stop = false;
|
private boolean stop = false;
|
||||||
|
|
||||||
ArrayList<Path> deleted = new ArrayList<>();
|
private ArrayList<Path> deleted = new ArrayList<>();
|
||||||
HashMap<String, ArrayList<ModFile>> changed = new HashMap<>();
|
private HashMap<String, ArrayList<ModFile>> changed = new HashMap<>();
|
||||||
int changedCount = 0;
|
int changedCount = 0;
|
||||||
HashMap<String, ArrayList<ModFile>> added = new HashMap<>();
|
private HashMap<String, ArrayList<ModFile>> added = new HashMap<>();
|
||||||
int addedCount = 0;
|
int addedCount = 0;
|
||||||
|
|
||||||
long size = 0;
|
long size = 0;
|
||||||
@ -66,7 +66,8 @@ public class FileChecker implements Observable {
|
|||||||
Mod m = (Mod) abstractMod;
|
Mod m = (Mod) abstractMod;
|
||||||
|
|
||||||
for (ModFile mf : m.getFiles()) {
|
for (ModFile mf : m.getFiles()) {
|
||||||
checkFile(mf.getName(), mf);
|
checkFile(m.getName(), mf);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
int finalI = i;
|
int finalI = i;
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
@ -99,16 +100,21 @@ public class FileChecker implements Observable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkFile(String mod, ModFile mf) {
|
private void checkFile(String mod, ModFile mf) {
|
||||||
// TODO: Add mf to Array if Array already exists
|
ArrayList<ModFile> temp = new ArrayList<>();
|
||||||
|
|
||||||
if(!mf.exists()) {
|
if(!mf.exists()) {
|
||||||
added.put(mod, mf);
|
if(added.containsKey(mod)) temp =added.get(mod);
|
||||||
|
temp.add(mf);
|
||||||
|
added.put(mod, temp);
|
||||||
addedCount++;
|
addedCount++;
|
||||||
size += mf.getSize();
|
size += mf.getSize();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mf.getLocalSize() != mf.getSize()) {
|
if(mf.getLocalSize() != mf.getSize() || !mf.getSHA1Sum().equalsIgnoreCase(mf.getLocalGeneratedSHA1Sum())) {
|
||||||
changed.put(mod, mf);
|
if(changed.containsKey(mod)) temp =changed.get(mod);
|
||||||
|
temp.add(mf);
|
||||||
|
changed.put(mod, temp);
|
||||||
changedCount++;
|
changedCount++;
|
||||||
size += mf.getSize();
|
size += mf.getSize();
|
||||||
return;
|
return;
|
||||||
|
@ -151,16 +151,18 @@ public class RepositoryManger implements Observable {
|
|||||||
Iterator<String> keys = content.keys();
|
Iterator<String> keys = content.keys();
|
||||||
while (keys.hasNext()) {
|
while (keys.hasNext()) {
|
||||||
String modfile = keys.next();
|
String modfile = keys.next();
|
||||||
long modfilesize = content.getLong(modfile);
|
JSONObject jo = content.getJSONObject(modfile);
|
||||||
|
long modfilesize = jo.getLong("size");
|
||||||
|
String sha1 = jo.getString("sha1");
|
||||||
|
|
||||||
modFiles.add(new ModFile(new File(finalModPath + File.separator + modname + File.separator + modfile), modfile, modfilesize));
|
modFiles.add(new ModFile(new File(finalModPath + File.separator + modname + File.separator + modfile), modfile, modname, modfilesize, sha1));
|
||||||
RepositoryManger.MOD_LIST_SIZE++;
|
RepositoryManger.MOD_LIST_SIZE++;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOD_LIST.add(new Mod(modname, modsize, modFiles));
|
MOD_LIST.add(new Mod(modname, modsize, modFiles));
|
||||||
} else {
|
} else {
|
||||||
// Single File
|
// Single File
|
||||||
MOD_LIST.add(new ModFile(new File(finalModPath + File.separator + modname), modname, modsize));
|
MOD_LIST.add(new ModFile(new File(finalModPath + File.separator + modname), modname, modsize, jsonMod.getString("sha1")));
|
||||||
RepositoryManger.MOD_LIST_SIZE++;
|
RepositoryManger.MOD_LIST_SIZE++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
108
src/main/java/de/mc8051/arma3launcher/repo/SyncList.java
Normal file
108
src/main/java/de/mc8051/arma3launcher/repo/SyncList.java
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package de.mc8051.arma3launcher.repo;
|
||||||
|
|
||||||
|
import de.mc8051.arma3launcher.objects.AbstractMod;
|
||||||
|
import de.mc8051.arma3launcher.objects.Mod;
|
||||||
|
import de.mc8051.arma3launcher.objects.ModFile;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by gurkengewuerz.de on 26.03.2020.
|
||||||
|
*/
|
||||||
|
public class SyncList extends ArrayList<AbstractMod> {
|
||||||
|
|
||||||
|
private long size = 0;
|
||||||
|
private int count = 0;
|
||||||
|
|
||||||
|
private ArrayList<Path> deleted = new ArrayList<>();
|
||||||
|
|
||||||
|
private SyncList(long size, int count) {
|
||||||
|
this.size = size;
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SyncList() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeleted(ArrayList<Path> deleted) {
|
||||||
|
this.deleted = deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(AbstractMod abstractMod) {
|
||||||
|
addedMod(abstractMod);
|
||||||
|
return super.add(abstractMod);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends AbstractMod> c) {
|
||||||
|
for (AbstractMod abstractMod : c) {
|
||||||
|
addedMod(abstractMod);
|
||||||
|
}
|
||||||
|
return super.addAll(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addedMod(AbstractMod abstractMod) {
|
||||||
|
if (abstractMod instanceof Mod) {
|
||||||
|
Mod mod = (Mod) abstractMod;
|
||||||
|
for (ModFile mf : mod.getFiles()) {
|
||||||
|
size += mf.getSize();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
} else if (abstractMod instanceof ModFile) {
|
||||||
|
ModFile mf = (ModFile) abstractMod;
|
||||||
|
size += mf.getSize();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractMod remove(int index) {
|
||||||
|
AbstractMod abstractMod = get(index);
|
||||||
|
|
||||||
|
if (abstractMod instanceof Mod) {
|
||||||
|
Mod mod = (Mod) abstractMod;
|
||||||
|
for (ModFile mf : mod.getFiles()) {
|
||||||
|
size -= mf.getSize();
|
||||||
|
}
|
||||||
|
} else if (abstractMod instanceof ModFile) {
|
||||||
|
ModFile mf = (ModFile) abstractMod;
|
||||||
|
size -= mf.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.remove(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSize(long size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCount(int count) {
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SyncList clone() {
|
||||||
|
SyncList clone = new SyncList();
|
||||||
|
clone.addAll(this);
|
||||||
|
clone.getDeleted().addAll(deleted);
|
||||||
|
clone.setSize(size);
|
||||||
|
clone.setDeleted(deleted);
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Path> getDeleted() {
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,304 @@
|
|||||||
package de.mc8051.arma3launcher.repo;
|
package de.mc8051.arma3launcher.repo;
|
||||||
|
|
||||||
|
import co.bitshfted.xapps.zsync.Zsync;
|
||||||
|
import co.bitshfted.xapps.zsync.ZsyncException;
|
||||||
|
import co.bitshfted.xapps.zsync.ZsyncObserver;
|
||||||
|
import de.mc8051.arma3launcher.ArmA3Launcher;
|
||||||
|
import de.mc8051.arma3launcher.LauncherGUI;
|
||||||
|
import de.mc8051.arma3launcher.interfaces.Observable;
|
||||||
|
import de.mc8051.arma3launcher.interfaces.Observer;
|
||||||
|
import de.mc8051.arma3launcher.objects.AbstractMod;
|
||||||
|
import de.mc8051.arma3launcher.objects.ModFile;
|
||||||
|
import humanize.Humanize;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by gurkengewuerz.de on 25.03.2020.
|
* Created by gurkengewuerz.de on 25.03.2020.
|
||||||
*/
|
*/
|
||||||
public class Syncer {
|
public class Syncer extends ZsyncObserver implements Observable {
|
||||||
// FilenameUtils.directoryContains
|
|
||||||
|
private List<Observer> observerList = new ArrayList<>();
|
||||||
|
|
||||||
|
private boolean stopped = false;
|
||||||
|
private boolean paused = false;
|
||||||
|
private boolean running = false;
|
||||||
|
|
||||||
|
private ModFile currentDownload = null;
|
||||||
|
private SyncList modlist;
|
||||||
|
|
||||||
|
private boolean currentDownload_failed = false;
|
||||||
|
private boolean controlfile_downloaded = false;
|
||||||
|
private int failed = 0;
|
||||||
|
private int success = 0;
|
||||||
|
|
||||||
|
long syncSize;
|
||||||
|
int syncCount;
|
||||||
|
|
||||||
|
long downloadStarted;
|
||||||
|
long downloadEnded;
|
||||||
|
long downloadSize;
|
||||||
|
long downloadDownloaded;
|
||||||
|
|
||||||
|
private Zsync zsync;
|
||||||
|
private LauncherGUI gui;
|
||||||
|
|
||||||
|
public Syncer(LauncherGUI gui) {
|
||||||
|
zsync = new Zsync();
|
||||||
|
this.gui = gui;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sync(SyncList ml) {
|
||||||
|
modlist = ml;
|
||||||
|
|
||||||
|
stopped = false;
|
||||||
|
paused = false;
|
||||||
|
running = true;
|
||||||
|
|
||||||
|
currentDownload = null;
|
||||||
|
|
||||||
|
failed = 0;
|
||||||
|
success = 0;
|
||||||
|
|
||||||
|
syncSize = ml.getSize();
|
||||||
|
syncCount = ml.getCount();
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
gui.syncDownloadProgress.setMaximum(syncCount);
|
||||||
|
gui.syncDownloadProgress.setValue(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
boolean lastPause = false;
|
||||||
|
while (running) {
|
||||||
|
if (stopped) {
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (modlist.isEmpty()) {
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paused) {
|
||||||
|
if (!lastPause) {
|
||||||
|
lastPause = true;
|
||||||
|
notifyObservers("syncPaused");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (lastPause) {
|
||||||
|
lastPause = false;
|
||||||
|
notifyObservers("syncContinue");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentDownload != null) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractMod abstractMod = modlist.get(0);
|
||||||
|
|
||||||
|
ModFile mf = null;
|
||||||
|
if (abstractMod instanceof ModFile) {
|
||||||
|
mf = (ModFile) abstractMod;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mf != null) {
|
||||||
|
Zsync.Options o = new Zsync.Options();
|
||||||
|
o.setOutputFile(Paths.get(mf.getLocaleFile().getAbsolutePath()));
|
||||||
|
|
||||||
|
try {
|
||||||
|
currentDownload = mf;
|
||||||
|
currentDownload_failed = false;
|
||||||
|
controlfile_downloaded = false;
|
||||||
|
|
||||||
|
zsync.zsync(URI.create(mf.getRemoteFile() + ".zsync"), o, this);
|
||||||
|
} catch (ZsyncException | IllegalArgumentException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
modlist.remove(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteFiles();
|
||||||
|
cleanUpEmptyFolders();
|
||||||
|
|
||||||
|
if (stopped) {
|
||||||
|
notifyObservers("syncStopped");
|
||||||
|
} else {
|
||||||
|
notifyObservers("syncComplete");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finnishCurrent() {
|
||||||
|
modlist.remove(0);
|
||||||
|
currentDownload = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteFiles() {
|
||||||
|
modlist.getDeleted().stream()
|
||||||
|
.filter((p) -> p.toFile().exists())
|
||||||
|
.filter((p) -> p.toFile().canRead())
|
||||||
|
.filter((p) -> p.toFile().canWrite())
|
||||||
|
.forEach((p) -> p.toFile().delete());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanUpEmptyFolders() {
|
||||||
|
try {
|
||||||
|
String modPath = ArmA3Launcher.user_config.get("client", "modPath");
|
||||||
|
if (modPath == null) modPath = "";
|
||||||
|
if (modPath.isEmpty()) return;
|
||||||
|
Files.find(Paths.get(modPath),
|
||||||
|
Integer.MAX_VALUE,
|
||||||
|
(filePath, fileAttr) -> fileAttr.isDirectory())
|
||||||
|
.filter((p) -> p.toFile().canRead())
|
||||||
|
.filter((p) -> p.toFile().canWrite())
|
||||||
|
.filter((p) -> p.toFile().list().length == 0)
|
||||||
|
.forEach((p) -> p.toFile().delete());
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void zsyncStarted(URI requestedZsyncUri, Zsync.Options options) {
|
||||||
|
super.zsyncStarted(requestedZsyncUri, options);
|
||||||
|
System.out.println("ZSync started " + options.getOutputFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void controlFileDownloadingComplete() {
|
||||||
|
super.controlFileDownloadingComplete();
|
||||||
|
System.out.println("controlFileDownloadingComplete");
|
||||||
|
controlfile_downloaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void zsyncFailed(Exception exception) {
|
||||||
|
super.zsyncFailed(exception);
|
||||||
|
currentDownload_failed = true;
|
||||||
|
System.out.println("Zsync failed " + exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void zsyncComplete() {
|
||||||
|
super.zsyncComplete();
|
||||||
|
|
||||||
|
downloadEnded = System.nanoTime();
|
||||||
|
System.out.println(downloadSize);
|
||||||
|
System.out.println(downloadEnded - downloadStarted);
|
||||||
|
System.out.println((downloadSize / (downloadEnded - downloadStarted)) / 1000);
|
||||||
|
|
||||||
|
System.out.println("Zsync complete");
|
||||||
|
|
||||||
|
if (currentDownload_failed)
|
||||||
|
failed++;
|
||||||
|
else success++;
|
||||||
|
|
||||||
|
final long finalSize = syncSize - modlist.getSize();
|
||||||
|
int i = success + failed;
|
||||||
|
int percentage = (int) ((double)i / (double)Long.valueOf(syncCount).intValue() * 100);
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
gui.syncDownloadProgress.setValue(i);
|
||||||
|
gui.syncDownloadedLabel.setText(Humanize.binaryPrefix(finalSize) + " " + " (" + failed + " failed)");
|
||||||
|
gui.syncDownloadProgress.setString(percentage + "%");
|
||||||
|
});
|
||||||
|
|
||||||
|
finnishCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void controlFileDownloadingStarted(URI uri, long length) {
|
||||||
|
super.controlFileDownloadingStarted(uri, length);
|
||||||
|
System.out.println("controlFileDownloadingStarted " + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteFileDownloadingStarted(URI uri, long length) {
|
||||||
|
super.remoteFileDownloadingStarted(uri, length);
|
||||||
|
System.out.println("remoteFileDownloadingStarted " + length);
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
gui.syncFileProgress.setMaximum(Long.valueOf(length).intValue());
|
||||||
|
gui.syncFileProgress.setValue(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
downloadSize = length;
|
||||||
|
downloadDownloaded = 0;
|
||||||
|
downloadStarted = System.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bytesDownloaded(long bytes) {
|
||||||
|
super.bytesDownloaded(bytes);
|
||||||
|
// System.out.println("Downloaded " + bytes);
|
||||||
|
downloadDownloaded += bytes;
|
||||||
|
|
||||||
|
// TODO: Fix file Download Progress
|
||||||
|
if (controlfile_downloaded) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
gui.syncFileProgress.setValue(Long.valueOf(downloadDownloaded).intValue());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isStopped() {
|
||||||
|
return stopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPaused() {
|
||||||
|
return paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRunning() {
|
||||||
|
return running;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
this.stopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPaused(boolean paused) {
|
||||||
|
this.paused = paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCountFailed() {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCountSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addObserver(Observer observer) {
|
||||||
|
observerList.add(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeObserver(Observer observer) {
|
||||||
|
observerList.remove(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyObservers(String obj) {
|
||||||
|
for (Observer obs : observerList) obs.update(obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,12 @@ collapse_all=Alles einklappen
|
|||||||
same_mod_arma_dir_msg=Das ArmA sowie Mod Verzeichnis dürfen nicht identisch sein.
|
same_mod_arma_dir_msg=Das ArmA sowie Mod Verzeichnis dürfen nicht identisch sein.
|
||||||
same_mod_arma_dir=Gleiches Verzeichnis
|
same_mod_arma_dir=Gleiches Verzeichnis
|
||||||
check_local_addons=Lokale Dateien überprüfen
|
check_local_addons=Lokale Dateien überprüfen
|
||||||
changed_files=Veränderte Datien
|
changed_filesize=Veränderte Größe
|
||||||
added_files=Hinzugefügte Datien
|
added_files=Hinzugefügte Dateien
|
||||||
deleted_files=Gelöschte Dateien
|
deleted_files=Gelöschte Dateien
|
||||||
|
changed_filesize=Veränderte Größe
|
||||||
|
changed_filesize_tooltip=Dies ist die ungefähre Dateigröße die Maximal runtergeladen wird
|
||||||
|
resume=Fortsetzen
|
||||||
|
changed_filesize=Veränderte Dateien
|
||||||
|
changed_files=Geänderte Dateien
|
||||||
|
file_count=Dateianzahl
|
@ -86,3 +86,12 @@ repository_content=Repository Content
|
|||||||
collapse_all=Collapse All
|
collapse_all=Collapse All
|
||||||
same_mod_arma_dir_msg=The ArmA and Mod directory must not be identical.
|
same_mod_arma_dir_msg=The ArmA and Mod directory must not be identical.
|
||||||
same_mod_arma_dir=Same directory
|
same_mod_arma_dir=Same directory
|
||||||
|
resume=Resume
|
||||||
|
added_files=Added files
|
||||||
|
deleted_files=Deleted files
|
||||||
|
update_repository=Update repository
|
||||||
|
check_local_addons=Check local files
|
||||||
|
changed_filesize=Changed size
|
||||||
|
changed_files=Changed files
|
||||||
|
changed_filesize_tooltip=This is the approximate maximum file size that will be downloaded
|
||||||
|
file_count=Number of files
|
Loading…
Reference in New Issue
Block a user