Skip to content

Commit

Permalink
- fix splashscreen not showing black background only on windows and l…
Browse files Browse the repository at this point in the history
…inux

- implement duplicate overview dialog
- introduce config variable ApplicationConfiguration.FILM_EVALUATE_DUPLICATES
- refactor out CommonStatsEvaluationTask
- code cleanup
- relax error reporting in DatenFilm.setDatumLong
  • Loading branch information
derreisende77 committed Oct 24, 2024
1 parent 0affbfb commit 1f4cd52
Show file tree
Hide file tree
Showing 13 changed files with 531 additions and 92 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- **BUGFIX:** Der "Filmliste laden"-Dialog zeigt nun Scrollbars bei zu kleiner Dialoggröße an.
- **BUGFIX(Linux):** Inkorrekte Verarbeitung der Parent-Beziehung bei Auswahldialogen wurde behoben.
- **BUGFIX(Linux):** MV öffnet nun einen konfigurierten Browser im About-Dialog wenn Java keinen eigenen finden kann.
- **BUGFIX(Linux/Windows):** Splashscreen zeigte keinen uniformen schwarzen Hintergrund mehr an.
- **FEATURE(Linux/Windows):** Das Aussehen von FlatLaf kann in `.mediathek3/flatlaf` angepasst werden.
- **FEATURE:** Selektierte Einträge in `Suchhistorie bearbeiten`-Dialog können nun mittels Entfernen-Taste gelöscht werden.
- **FEATURE:** Das Blacklist Filter-Icon in der Toolbar kann mittels *Einstellungen/Allgemein* mit einem aussagefähigen Zusatztext dargestellt werden.
Expand All @@ -29,6 +30,7 @@
- **FEATURE:** Im Tab `Filme` können über das Kontextmenü `Zusammengehörige Filme anzeigen...` bei einem markierten Duplikat alle zusammengehörigen Filme angezeigt werden.
- **FEATURE:** Mittels `Ansicht/Filmstatistik anzeigen` können nun für die vorhandenen Sender Informationen bzgl. Anzahl der Filme und der Duplikate angezeigt werden. Es wird hier nur die gesamte Filmliste ohne jegliche Filter abzüglich Livestreams berücksichtigt, so dass es zu Abweichungen zur Anzeige in der Statuszeile kommen kann.
- **FEATURE:** Mit der Lucene-Suche können mittels des `duplicate`-Boolean Parameters Filmduplikate berücksichtigt werden.
- **FEATURE:** Via `Ansicht/Übersicht aller Duplikate anzeigen...` werden in einem Dialog per Sender alle vorhandenen Duplikate dargestellt zzgl. der zugeordneten Filme.

# **14.1.0**
- JDK 21 wird nun mitgeliefert. Behebt primär Darstellungsfehler von Java Apps unter Windows.
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/mediathek/daten/DatenFilm.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public void setDatumLong(String datumLong) {
datum_long = Long.parseLong(datumLong);
}
catch (Exception e) {
logger.error("Failed to parse datum long string", e);
logger.warn("Failed to parse datum long string: {}", datumLong);
datum_long = 0;
}
dataMap.put(MapKeys.TEMP_DATUM_LONG, datum_long);
Expand Down Expand Up @@ -421,7 +421,7 @@ private void setupDatumFilm() {
if (!getSendeDatum().isEmpty()) {
// nur dann gibts ein Datum
long datum_long = (long)dataMap.getOrDefault(MapKeys.TEMP_DATUM_LONG, 0L);
datumFilm = new DatumFilm(datum_long * 1000); // convert from SECONDS to MILLISECONDS
datumFilm = new DatumFilm(TimeUnit.MILLISECONDS.convert(datum_long, TimeUnit.SECONDS));
if (datum_long == 0)
{
setSendeDatum("");
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/mediathek/filmlisten/FilmeLaden.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import mediathek.filmeSuchen.ListenerFilmeLaden;
import mediathek.filmeSuchen.ListenerFilmeLadenEvent;
import mediathek.filmlisten.reader.FilmListReader;
import mediathek.gui.duplicates.CommonStatsEvaluationTask;
import mediathek.gui.duplicates.FilmDuplicateEvaluationTask;
import mediathek.gui.messages.FilmListReadStopEvent;
import mediathek.gui.tasks.BlacklistFilterWorker;
Expand Down Expand Up @@ -317,8 +318,13 @@ private void undEnde(ListenerFilmeLadenEvent event) {
throw new RuntimeException(e);
}
var workerTask = CompletableFuture.runAsync(new RefreshAboWorker(progLabel, progressBar))
.thenRun(new BlacklistFilterWorker(progLabel, progressBar))
.thenRun(new FilmDuplicateEvaluationTask());
.thenRun(new BlacklistFilterWorker(progLabel, progressBar));

var evaluateDuplicates = ApplicationConfiguration.getConfiguration().getBoolean(ApplicationConfiguration.FILM_EVALUATE_DUPLICATES, true);
if (evaluateDuplicates) {
workerTask = workerTask.thenRun(new FilmDuplicateEvaluationTask());
}
workerTask = workerTask.thenRun(new CommonStatsEvaluationTask());

if (writeFilmList) {
workerTask = workerTask.thenRun(new FilmlistWriterWorker(progLabel, progressBar));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ private void writeEntry(DatenFilm datenFilm, JsonGenerator jg) throws IOExceptio
skipEntry(jg); //DatenFilm.URL_RTMP_KLEIN
writeHighQualityUrl(jg, datenFilm);
skipEntry(jg); //DatenFilm.FILM_URL_RTMP_HD
jg.writeString(String.valueOf(datenFilm.getDatumFilm().getTime() / 1000));
jg.writeString(String.valueOf(TimeUnit.SECONDS.convert(datenFilm.getDatumFilm().getTime(), TimeUnit.MILLISECONDS)));
skipEntry(jg); //DatenFilm.FILM_URL_HISTORY
if (datenFilm.countrySet.isEmpty())
jg.writeString("");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package mediathek.gui.duplicates;

import mediathek.daten.DatenFilm;

import java.util.Comparator;

public class BigSenderPenaltyComparator implements Comparator<DatenFilm> {
@Override
public int compare(DatenFilm s1, DatenFilm s2) {
// "ARD" und "ZDF" immer am Ende um die kleineren Mediatheken nicht zu benachteiligen
final var s1_sender = s1.getSender();
final var s2_sender = s2.getSender();
if (s1_sender.equals("ARD") || s1_sender.equals("ZDF")) {
return 1;
}
if (s2_sender.equals("ARD") || s2_sender.equals("ZDF")) {
return -1;
}
// Alphabetisch sortieren für alle anderen
return s1.compareTo(s2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package mediathek.gui.duplicates;

import ca.odell.glazedlists.TransactionList;
import com.google.common.base.Stopwatch;
import mediathek.config.Daten;
import mediathek.daten.DatenFilm;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Map;
import java.util.stream.Collectors;

public class CommonStatsEvaluationTask implements Runnable {
private static final Logger logger = LogManager.getLogger();

@Override
public void run() {
Stopwatch watch = Stopwatch.createStarted();
final var films = Daten.getInstance().getListeFilme().parallelStream()
.filter(f -> !f.isLivestream())
.toList();

var statisticsList = Daten.getInstance().getCommonStatistics();

Map<String, Long> statisticsMap = films.parallelStream()
.collect(Collectors.groupingBy(DatenFilm::getSender, Collectors.counting()));
TransactionList<FilmStatistics> tList = new TransactionList<>(statisticsList);
statisticsList.getReadWriteLock().writeLock().lock();
tList.beginEvent(true);
tList.clear();
for (var sender : statisticsMap.keySet()) {
tList.add(new FilmStatistics(sender, statisticsMap.get(sender)));
}
tList.commitEvent();
statisticsList.getReadWriteLock().writeLock().unlock();
watch.stop();

logger.trace("common stats calculation took: {}", watch);
logger.trace("Number of films: {}", films.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.apache.logging.log4j.Logger;

import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -35,10 +34,12 @@ private void printDuplicateStatistics() {
Map<String, Long> statisticsMap = duplicates.parallelStream().collect(Collectors.groupingBy(DatenFilm::getSender, Collectors.counting()));
TransactionList<FilmStatistics> tList = new TransactionList<>(statisticsEventList);
tList.getReadWriteLock().writeLock().lock();
tList.beginEvent(true);
tList.clear();
for (var sender : statisticsMap.keySet()) {
tList.add(new FilmStatistics(sender, statisticsMap.get(sender)));
}
tList.commitEvent();
tList.getReadWriteLock().writeLock().unlock();
watch.stop();

Expand Down Expand Up @@ -70,50 +71,9 @@ private void checkDuplicates() {
urlCache.clear();
}

private void calculateCommonStats() {
Stopwatch watch = Stopwatch.createStarted();
final var films = listeFilme.parallelStream()
.filter(f -> !f.isLivestream())
.toList();

var statisticsList = Daten.getInstance().getCommonStatistics();

Map<String, Long> statisticsMap = films.parallelStream()
.collect(Collectors.groupingBy(DatenFilm::getSender, Collectors.counting()));
TransactionList<FilmStatistics> tList = new TransactionList<>(statisticsList);
tList.getReadWriteLock().writeLock().lock();
tList.clear();
for (var sender : statisticsMap.keySet()) {
tList.add(new FilmStatistics(sender, statisticsMap.get(sender)));
}
tList.getReadWriteLock().writeLock().unlock();
watch.stop();

logger.trace("common stats calculation took: {}", watch);
logger.trace("Number of films: {}", films.size());
}

@Override
public void run() {
calculateCommonStats();
checkDuplicates();
printDuplicateStatistics();
}

private static class BigSenderPenaltyComparator implements Comparator<DatenFilm> {
@Override
public int compare(DatenFilm s1, DatenFilm s2) {
// "ARD" und "ZDF" immer am Ende um die kleineren Mediatheken nicht zu benachteiligen
final var s1_sender = s1.getSender();
final var s2_sender = s2.getSender();
if (s1_sender.equals("ARD") || s1_sender.equals("ZDF")) {
return 1;
}
if (s2_sender.equals("ARD") || s2_sender.equals("ZDF")) {
return -1;
}
// Alphabetisch sortieren für alle anderen
return s1.compareTo(s2);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package mediathek.gui.duplicates.overview;

import mediathek.daten.DatenFilm;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;

class CustomTreeCellRenderer
extends DefaultTreeCellRenderer {
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
// Allow the original renderer to set up the label
Component c = super.getTreeCellRendererComponent(
tree, value, selected,
expanded, leaf, row,
hasFocus);

var node = (DefaultMutableTreeNode) value;
if (node.isRoot())
return c;

switch (node.getUserObject()) {
case DatenFilm f -> {
setText(f.getTitle());
setToolTipText(prepareTooltipText(f));
}
case String s -> setText(String.format("%s (%d)", s, node.getChildCount()));
default -> setText(value.toString());
}

return c;
}

private String prepareTooltipText(DatenFilm f) {
var s = """
<html>
<b>Thema:</b> %s<br>
<b>Titel:</b> %s<br>
<b>gesendet:</b> %s %s<br>
</html>
""";
return String.format(s, f.getThema(), f.getTitle(),
f.getSendeDatum(), f.getSendeZeit());
}
}
Loading

0 comments on commit 1f4cd52

Please sign in to comment.