mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 01:27:34 -05:00
#766 Resolves issue with playlist alias editor clone alias feature causing multiple copies of alias. Changed clone feature to only use a shallow copy (no ids or actions). Removed alias event framework from code since all change notifications can now be detected by the alias model's aliasList property. (#791)
Co-authored-by: Denny <denny@denny-desktop>
This commit is contained in:
@@ -1,55 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* SDR Trunk
|
|
||||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>
|
|
||||||
******************************************************************************/
|
|
||||||
package io.github.dsheirer.alias;
|
|
||||||
|
|
||||||
public class AliasEvent
|
|
||||||
{
|
|
||||||
private Alias mAlias;
|
|
||||||
private Event mEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AliasEvent - event describing any changes to an alias
|
|
||||||
* @param alias - alias that changed
|
|
||||||
* @param event - change event
|
|
||||||
*/
|
|
||||||
public AliasEvent( Alias alias, Event event )
|
|
||||||
{
|
|
||||||
mAlias = alias;
|
|
||||||
mEvent = event;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Alias getAlias()
|
|
||||||
{
|
|
||||||
return mAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Event getEvent()
|
|
||||||
{
|
|
||||||
return mEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel events to describe the specific event
|
|
||||||
*/
|
|
||||||
public enum Event
|
|
||||||
{
|
|
||||||
ADD,
|
|
||||||
CHANGE,
|
|
||||||
DELETE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -51,6 +51,9 @@ import io.github.dsheirer.alias.id.tone.TonesID;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class AliasFactory
|
public class AliasFactory
|
||||||
{
|
{
|
||||||
private static final Logger mLog = LoggerFactory.getLogger(AliasFactory.class);
|
private static final Logger mLog = LoggerFactory.getLogger(AliasFactory.class);
|
||||||
@@ -180,32 +183,56 @@ public class AliasFactory
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Alias copyOf(Alias original)
|
public static Alias shallowCopyOf(Alias original)
|
||||||
{
|
{
|
||||||
Alias copy = new Alias(original.getName());
|
Alias copy = new Alias(original.getName());
|
||||||
copy.setAliasListName(original.getAliasListName());
|
copy.setAliasListName(original.getAliasListName());
|
||||||
copy.setGroup(original.getGroup());
|
copy.setGroup(original.getGroup());
|
||||||
copy.setColor(original.getColor());
|
copy.setColor(original.getColor());
|
||||||
copy.setIconName(original.getIconName());
|
copy.setIconName(original.getIconName());
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<AliasID> copyAliasIDs(Alias original)
|
||||||
|
{
|
||||||
|
List<AliasID> aliasIDS = new ArrayList<>();
|
||||||
|
|
||||||
for(AliasID id : original.getAliasIdentifiers())
|
for(AliasID id : original.getAliasIdentifiers())
|
||||||
{
|
{
|
||||||
AliasID copyID = copyOf(id);
|
aliasIDS.add(copyOf(id));
|
||||||
|
|
||||||
if(copyID != null)
|
|
||||||
{
|
|
||||||
copy.addAliasID(copyID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(AliasAction action : original.getAliasActions())
|
return aliasIDS;
|
||||||
{
|
}
|
||||||
AliasAction copyAction = copyOf(action);
|
|
||||||
|
|
||||||
if(copyAction != null)
|
public static List<AliasAction> copyAliasActions(Alias original)
|
||||||
{
|
{
|
||||||
copy.addAliasAction(copyAction);
|
List<AliasAction> actions = new ArrayList<>();
|
||||||
}
|
|
||||||
|
for(AliasAction aliasAction: original.getAliasActions())
|
||||||
|
{
|
||||||
|
actions.add(copyOf(aliasAction));
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Alias copyOf(Alias original)
|
||||||
|
{
|
||||||
|
Alias copy = shallowCopyOf(original);
|
||||||
|
|
||||||
|
List<AliasID> aliasIDS = copyAliasIDs(original);
|
||||||
|
|
||||||
|
for(AliasID aliasID: aliasIDS)
|
||||||
|
{
|
||||||
|
copy.addAliasID(aliasID);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AliasAction> actions = copyAliasActions(original);
|
||||||
|
|
||||||
|
for(AliasAction action: actions)
|
||||||
|
{
|
||||||
|
copy.addAliasAction(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
|
|||||||
@@ -45,19 +45,27 @@ import io.github.dsheirer.identifier.talkgroup.TalkgroupIdentifier;
|
|||||||
import io.github.dsheirer.identifier.tone.ToneIdentifier;
|
import io.github.dsheirer.identifier.tone.ToneIdentifier;
|
||||||
import io.github.dsheirer.identifier.tone.ToneSequence;
|
import io.github.dsheirer.identifier.tone.ToneSequence;
|
||||||
import io.github.dsheirer.protocol.Protocol;
|
import io.github.dsheirer.protocol.Protocol;
|
||||||
import io.github.dsheirer.sample.Listener;
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of aliases that share the same alias list name and provides convenient methods for looking up alias
|
* List of aliases that share the same alias list name and provides convenient methods for looking up alias
|
||||||
* objects that match an identifier.
|
* objects that match an identifier.
|
||||||
*/
|
*/
|
||||||
public class AliasList implements Listener<AliasEvent>
|
public class AliasList
|
||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(AliasList.class);
|
private final static Logger mLog = LoggerFactory.getLogger(AliasList.class);
|
||||||
private Map<Protocol,TalkgroupAliasList> mTalkgroupProtocolMap = new EnumMap<>(Protocol.class);
|
private Map<Protocol,TalkgroupAliasList> mTalkgroupProtocolMap = new EnumMap<>(Protocol.class);
|
||||||
@@ -96,10 +104,7 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
{
|
{
|
||||||
if(alias != null)
|
if(alias != null)
|
||||||
{
|
{
|
||||||
for(AliasID aliasID : alias.getAliasIdentifiers())
|
alias.getAliasIdentifiers().stream().forEach(aliasID -> addAliasID(aliasID, alias));
|
||||||
{
|
|
||||||
addAliasID(aliasID, alias);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(alias.hasActions())
|
if(alias.hasActions())
|
||||||
@@ -107,7 +112,10 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
mHasAliasActions = true;
|
mHasAliasActions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mAliases.add(alias);
|
if(!mAliases.contains(alias))
|
||||||
|
{
|
||||||
|
mAliases.add(alias);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,7 +182,7 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
radioRangeAliasList.add(radioRange, alias);
|
radioRangeAliasList.add(radioRange, alias);
|
||||||
break;
|
break;
|
||||||
case ESN:
|
case ESN:
|
||||||
String esn = ((Esn) id).getEsn();
|
String esn = ((Esn)id).getEsn();
|
||||||
|
|
||||||
if(esn != null && !esn.isEmpty())
|
if(esn != null && !esn.isEmpty())
|
||||||
{
|
{
|
||||||
@@ -184,7 +192,7 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
case STATUS:
|
case STATUS:
|
||||||
int userStatus = ((UserStatusID)id).getStatus();
|
int userStatus = ((UserStatusID)id).getStatus();
|
||||||
|
|
||||||
if(mUserStatusMap.containsKey(userStatus))
|
if(mUserStatusMap.containsKey(userStatus) && !mUserStatusMap.get(userStatus).equals(alias))
|
||||||
{
|
{
|
||||||
id.setOverlap(true);
|
id.setOverlap(true);
|
||||||
|
|
||||||
@@ -203,7 +211,7 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
case UNIT_STATUS:
|
case UNIT_STATUS:
|
||||||
int unitStatus = ((UnitStatusID)id).getStatus();
|
int unitStatus = ((UnitStatusID)id).getStatus();
|
||||||
|
|
||||||
if(mUnitStatusMap.containsKey(unitStatus))
|
if(mUnitStatusMap.containsKey(unitStatus) && !mUnitStatusMap.get(unitStatus).equals(alias))
|
||||||
{
|
{
|
||||||
id.setOverlap(true);
|
id.setOverlap(true);
|
||||||
|
|
||||||
@@ -224,7 +232,7 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
|
|
||||||
if(toneSequence != null)
|
if(toneSequence != null)
|
||||||
{
|
{
|
||||||
if(mToneSequenceMap.containsKey(toneSequence))
|
if(mToneSequenceMap.containsKey(toneSequence) && !mToneSequenceMap.get(toneSequence).equals(alias))
|
||||||
{
|
{
|
||||||
id.setOverlap(true);
|
id.setOverlap(true);
|
||||||
|
|
||||||
@@ -232,7 +240,7 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
|
|
||||||
for(AliasID aliasID: existing.getAliasIdentifiers())
|
for(AliasID aliasID: existing.getAliasIdentifiers())
|
||||||
{
|
{
|
||||||
if(aliasID instanceof TonesID && ((TonesID)aliasID).equals(id))
|
if(aliasID instanceof TonesID && aliasID.equals(id))
|
||||||
{
|
{
|
||||||
aliasID.setOverlap(true);
|
aliasID.setOverlap(true);
|
||||||
}
|
}
|
||||||
@@ -253,112 +261,50 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the alias and alias identifier to the internal type mapping.
|
|
||||||
*/
|
|
||||||
private void removeAliasID(AliasID id, Alias alias)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch(id.getType())
|
|
||||||
{
|
|
||||||
case TALKGROUP:
|
|
||||||
Talkgroup talkgroup = (Talkgroup)id;
|
|
||||||
|
|
||||||
TalkgroupAliasList talkgroupAliasList = mTalkgroupProtocolMap.get(talkgroup.getProtocol());
|
|
||||||
|
|
||||||
if(talkgroupAliasList != null)
|
|
||||||
{
|
|
||||||
talkgroupAliasList.remove(talkgroup, alias);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TALKGROUP_RANGE:
|
|
||||||
TalkgroupRange talkgroupRange = (TalkgroupRange)id;
|
|
||||||
|
|
||||||
TalkgroupAliasList talkgroupRangeAliasList = mTalkgroupProtocolMap.get(talkgroupRange.getProtocol());
|
|
||||||
|
|
||||||
if(talkgroupRangeAliasList != null)
|
|
||||||
{
|
|
||||||
talkgroupRangeAliasList.remove(talkgroupRange, alias);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RADIO_ID:
|
|
||||||
Radio radio = (Radio)id;
|
|
||||||
|
|
||||||
RadioAliasList radioAliasList = mRadioProtocolMap.get(radio.getProtocol());
|
|
||||||
|
|
||||||
if(radioAliasList != null)
|
|
||||||
{
|
|
||||||
radioAliasList.remove(radio, alias);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RADIO_ID_RANGE:
|
|
||||||
RadioRange radioRange = (RadioRange)id;
|
|
||||||
|
|
||||||
RadioAliasList radioRangeAliasList = mRadioProtocolMap.get(radioRange.getProtocol());
|
|
||||||
|
|
||||||
if(radioRangeAliasList != null)
|
|
||||||
{
|
|
||||||
radioRangeAliasList.remove(radioRange, alias);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ESN:
|
|
||||||
String esn = ((Esn) id).getEsn();
|
|
||||||
|
|
||||||
if(esn != null && !esn.isEmpty())
|
|
||||||
{
|
|
||||||
String key = esn.toLowerCase();
|
|
||||||
|
|
||||||
if(mESNMap.containsKey(key) && mESNMap.get(key) == alias)
|
|
||||||
{
|
|
||||||
mESNMap.remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATUS:
|
|
||||||
int status = ((UserStatusID)id).getStatus();
|
|
||||||
|
|
||||||
if(mUserStatusMap.containsKey(status) && mUserStatusMap.get(status) == alias)
|
|
||||||
{
|
|
||||||
mUserStatusMap.remove(status);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case UNIT_STATUS:
|
|
||||||
int unitStatus = ((UnitStatusID)id).getStatus();
|
|
||||||
|
|
||||||
if(mUnitStatusMap.containsKey(unitStatus) && mUnitStatusMap.get(unitStatus) == alias)
|
|
||||||
{
|
|
||||||
mUnitStatusMap.remove(unitStatus);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TONES:
|
|
||||||
ToneSequence toneSequence = ((TonesID)id).getToneSequence();
|
|
||||||
|
|
||||||
if(toneSequence != null && mToneSequenceMap.containsKey(toneSequence) &&
|
|
||||||
mToneSequenceMap.get(toneSequence) == alias)
|
|
||||||
{
|
|
||||||
mToneSequenceMap.remove(toneSequence);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
mLog.error("Couldn't remove alias ID " + id + " for alias " + alias, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the alias from this list
|
* Removes the alias from this list
|
||||||
*/
|
*/
|
||||||
public void removeAlias(Alias alias)
|
public void removeAlias(Alias alias)
|
||||||
{
|
{
|
||||||
for(AliasID aliasID: alias.getAliasIdentifiers())
|
//Note: because the alias' identifiers could have changed from when we initially added the alias, we have to
|
||||||
|
//inspect every collection and map to remove the alias completely.
|
||||||
|
mAliases.remove(alias);
|
||||||
|
|
||||||
|
mTalkgroupProtocolMap.values().stream().forEach(talkgroupAliasList -> talkgroupAliasList.remove(alias));
|
||||||
|
mRadioProtocolMap.values().stream().forEach(radioAliasList -> radioAliasList.remove(alias));
|
||||||
|
|
||||||
|
Collection<Alias> collection = Collections.singleton(alias);
|
||||||
|
mESNMap.values().removeAll(collection);
|
||||||
|
mUnitStatusMap.values().removeAll(collection);
|
||||||
|
mUserStatusMap.values().removeAll(collection);
|
||||||
|
mToneSequenceMap.values().removeAll(collection);
|
||||||
|
|
||||||
|
validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies all aliases with an alias identifier that has the overlap flag set, resets the flag, and then readds
|
||||||
|
* each alias back to this alias list so that overlap can be detected again.
|
||||||
|
*/
|
||||||
|
public void validate()
|
||||||
|
{
|
||||||
|
Set<Alias> overlapAliases = new HashSet<>();
|
||||||
|
|
||||||
|
List<Alias> aliases = new ArrayList<>(mAliases);
|
||||||
|
|
||||||
|
for(Alias alias: aliases)
|
||||||
{
|
{
|
||||||
removeAliasID(aliasID, alias);
|
for(AliasID aliasID: alias.getAliasIdentifiers())
|
||||||
|
{
|
||||||
|
if(aliasID.overlapProperty().get())
|
||||||
|
{
|
||||||
|
aliasID.setOverlap(false);
|
||||||
|
overlapAliases.add(alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mAliases.remove(alias);
|
overlapAliases.stream().forEach(alias -> addAlias(alias));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,32 +348,15 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receive alias change event notifications and modify this list accordingly
|
* Updates the alias by removing it from this list and then adding it back to this list when the list name matches.
|
||||||
*/
|
*/
|
||||||
@Override
|
public void updateAlias(Alias alias)
|
||||||
public void receive(AliasEvent event)
|
|
||||||
{
|
{
|
||||||
if(hasName())
|
removeAlias(alias);
|
||||||
{
|
|
||||||
Alias alias = event.getAlias();
|
|
||||||
|
|
||||||
switch(event.getEvent())
|
if(hasName() && getName().equals(alias.getAliasListName()))
|
||||||
{
|
{
|
||||||
case ADD:
|
addAlias(alias);
|
||||||
if(alias.getAliasListName() != null && getName().equalsIgnoreCase(alias.getAliasListName()))
|
|
||||||
{
|
|
||||||
addAlias(alias);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DELETE:
|
|
||||||
if(alias.getAliasListName() != null && getName().equalsIgnoreCase(alias.getAliasListName()))
|
|
||||||
{
|
|
||||||
removeAlias(alias);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,34 +588,6 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Identifies all aliases that have alias identifiers that match the alias ID and are in the same alias list.
|
|
||||||
* @param alias for the list to search
|
|
||||||
* @param aliasID to find matches
|
|
||||||
* @return list of one or more aliases that have matching alias identifiers
|
|
||||||
*/
|
|
||||||
public List<Alias> getOverlappingAliases(Alias alias, AliasID aliasID)
|
|
||||||
{
|
|
||||||
List<Alias> aliases = new ArrayList<>();
|
|
||||||
|
|
||||||
for(Alias otherAlias: mAliases)
|
|
||||||
{
|
|
||||||
if(otherAlias != alias)
|
|
||||||
{
|
|
||||||
for(AliasID otherId: otherAlias.getAliasIdentifiers())
|
|
||||||
{
|
|
||||||
if(otherId.matches(aliasID) || otherId.overlaps(aliasID))
|
|
||||||
{
|
|
||||||
aliases.add(otherAlias);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return aliases;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listing of talkgroups and ranges for a specific protocol
|
* Listing of talkgroups and ranges for a specific protocol
|
||||||
*/
|
*/
|
||||||
@@ -759,21 +660,13 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
mTalkgroupRangeAliasMap.put(talkgroupRange, alias);
|
mTalkgroupRangeAliasMap.put(talkgroupRange, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(Talkgroup talkgroup, Alias alias)
|
/**
|
||||||
|
* Removes the alias from both the talkgroup and the talkgroup range maps.
|
||||||
|
*/
|
||||||
|
public void remove(Alias alias)
|
||||||
{
|
{
|
||||||
if(mTalkgroupAliasMap.containsKey(talkgroup.getValue()) && mTalkgroupAliasMap.get(talkgroup.getValue()) == alias)
|
mTalkgroupAliasMap.values().removeAll(Collections.singleton(alias));
|
||||||
{
|
mTalkgroupRangeAliasMap.values().removeAll(Collections.singleton(alias));
|
||||||
mTalkgroupAliasMap.remove(talkgroup.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(TalkgroupRange talkgroupRange, Alias alias)
|
|
||||||
{
|
|
||||||
//Only remove the entry if both the key and the value match
|
|
||||||
if(mTalkgroupRangeAliasMap.containsKey(talkgroupRange) && mTalkgroupRangeAliasMap.get(talkgroupRange) == alias)
|
|
||||||
{
|
|
||||||
mTalkgroupRangeAliasMap.remove(talkgroupRange);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,22 +742,13 @@ public class AliasList implements Listener<AliasEvent>
|
|||||||
mRadioRangeAliasMap.put(radioRange, alias);
|
mRadioRangeAliasMap.put(radioRange, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(Radio radio, Alias alias)
|
/**
|
||||||
|
* Removes the alias from both the radio and the radio range maps.
|
||||||
|
*/
|
||||||
|
public void remove(Alias alias)
|
||||||
{
|
{
|
||||||
//Only remove the entry if both the key and the value match
|
mRadioAliasMap.values().removeAll(Collections.singleton(alias));
|
||||||
if(mRadioAliasMap.containsKey(radio.getValue()) && mRadioAliasMap.get(radio.getValue()) == alias)
|
mRadioRangeAliasMap.values().removeAll(Collections.singleton(alias));
|
||||||
{
|
|
||||||
mRadioAliasMap.remove(radio.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(RadioRange radioRange, Alias alias)
|
|
||||||
{
|
|
||||||
//Only remove the entry if both the key and the value match
|
|
||||||
if(mRadioRangeAliasMap.containsKey(radioRange) && mRadioRangeAliasMap.get(radioRange) == alias)
|
|
||||||
{
|
|
||||||
mRadioRangeAliasMap.remove(radioRange);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ import io.github.dsheirer.alias.id.AliasIDType;
|
|||||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||||
import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
|
import io.github.dsheirer.identifier.configuration.AliasListConfigurationIdentifier;
|
||||||
import io.github.dsheirer.sample.Broadcaster;
|
|
||||||
import io.github.dsheirer.sample.Listener;
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
@@ -51,7 +49,6 @@ public class AliasModel
|
|||||||
public static final String NO_ALIAS_LIST = "(No Alias List)";
|
public static final String NO_ALIAS_LIST = "(No Alias List)";
|
||||||
private ObservableList<Alias> mAliases = FXCollections.observableArrayList(Alias.extractor());
|
private ObservableList<Alias> mAliases = FXCollections.observableArrayList(Alias.extractor());
|
||||||
private ObservableList<String> mAliasListNames = FXCollections.observableArrayList();
|
private ObservableList<String> mAliasListNames = FXCollections.observableArrayList();
|
||||||
private Broadcaster<AliasEvent> mAliasEventBroadcaster = new Broadcaster<>();
|
|
||||||
private Map<String,AliasList> mAliasListMap = new HashMap<>();
|
private Map<String,AliasList> mAliasListMap = new HashMap<>();
|
||||||
|
|
||||||
public AliasModel()
|
public AliasModel()
|
||||||
@@ -135,7 +132,8 @@ public class AliasModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
AliasList mapValue = mAliasListMap.get(name);
|
AliasList mapValue = mAliasListMap.get(name);
|
||||||
if (mapValue != null) {
|
if (mapValue != null)
|
||||||
|
{
|
||||||
return mapValue;
|
return mapValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,9 +149,6 @@ public class AliasModel
|
|||||||
|
|
||||||
mAliasListMap.put(name, aliasList);
|
mAliasListMap.put(name, aliasList);
|
||||||
|
|
||||||
//Register the new alias list to receive updates from this model
|
|
||||||
addListener(aliasList);
|
|
||||||
|
|
||||||
return aliasList;
|
return aliasList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,18 +194,19 @@ public class AliasModel
|
|||||||
/**
|
/**
|
||||||
* Adds the alias to the model
|
* Adds the alias to the model
|
||||||
*/
|
*/
|
||||||
public int addAlias(Alias alias)
|
public void addAlias(Alias alias)
|
||||||
{
|
{
|
||||||
if(alias != null)
|
if(mAliases.contains(alias))
|
||||||
{
|
{
|
||||||
mAliases.add(alias);
|
removeAlias(alias);
|
||||||
addAliasList(alias.getAliasListName());
|
|
||||||
int index = mAliases.size() - 1;
|
|
||||||
broadcast(new AliasEvent(alias, AliasEvent.Event.ADD));
|
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
mAliases.add(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasAliasList(String aliasListName)
|
||||||
|
{
|
||||||
|
return aliasListName != null && mAliasListMap.containsKey(aliasListName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAliasList(String aliasListName)
|
public void addAliasList(String aliasListName)
|
||||||
@@ -220,7 +216,6 @@ public class AliasModel
|
|||||||
if(!mAliasListNames.contains(aliasListName))
|
if(!mAliasListNames.contains(aliasListName))
|
||||||
{
|
{
|
||||||
mAliasListNames.add(aliasListName);
|
mAliasListNames.add(aliasListName);
|
||||||
FXCollections.sort(mAliasListNames);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!mAliasListNames.contains(NO_ALIAS_LIST))
|
else if(!mAliasListNames.contains(NO_ALIAS_LIST))
|
||||||
@@ -232,14 +227,18 @@ public class AliasModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the channel from the model and broadcasts a channel remove event
|
* Removes the alias from this model and an alias list (if one exists)
|
||||||
*/
|
*/
|
||||||
public void removeAlias(Alias alias)
|
public void removeAlias(Alias alias)
|
||||||
{
|
{
|
||||||
if(alias != null)
|
if(alias != null)
|
||||||
{
|
{
|
||||||
mAliases.remove(alias);
|
mAliases.remove(alias);
|
||||||
broadcast(new AliasEvent(alias, AliasEvent.Event.DELETE));
|
|
||||||
|
if(hasAliasList(alias.getAliasListName()))
|
||||||
|
{
|
||||||
|
getAliasList(alias.getAliasListName()).removeAlias(alias);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,32 +327,8 @@ public class AliasModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(AliasEvent event)
|
|
||||||
{
|
|
||||||
Alias alias = event.getAlias();
|
|
||||||
|
|
||||||
//Validate the alias following a user action that changed the alias or any alias IDs
|
|
||||||
if(alias != null)
|
|
||||||
{
|
|
||||||
alias.validate();
|
|
||||||
}
|
|
||||||
|
|
||||||
mAliasEventBroadcaster.broadcast(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(Listener<AliasEvent> listener)
|
|
||||||
{
|
|
||||||
mAliasEventBroadcaster.addListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeListener(Listener<AliasEvent> listener)
|
|
||||||
{
|
|
||||||
mAliasEventBroadcaster.removeListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observable list change listener for both channels and traffic channels lists
|
* Monitors alias additions and removals and updates alias lists
|
||||||
*/
|
*/
|
||||||
public class AliasListChangeListener implements ListChangeListener<Alias>
|
public class AliasListChangeListener implements ListChangeListener<Alias>
|
||||||
{
|
{
|
||||||
@@ -366,21 +341,27 @@ public class AliasModel
|
|||||||
{
|
{
|
||||||
for(Alias alias: change.getAddedSubList())
|
for(Alias alias: change.getAddedSubList())
|
||||||
{
|
{
|
||||||
mAliasEventBroadcaster.broadcast(new AliasEvent(alias, AliasEvent.Event.ADD));
|
addAliasList(alias.getAliasListName());
|
||||||
|
|
||||||
|
if(hasAliasList(alias.getAliasListName()))
|
||||||
|
{
|
||||||
|
getAliasList(alias.getAliasListName()).addAlias(alias);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(change.wasRemoved())
|
else if(change.wasRemoved())
|
||||||
{
|
{
|
||||||
for(Alias alias: change.getRemoved())
|
for(Alias alias: change.getRemoved())
|
||||||
{
|
{
|
||||||
mAliasEventBroadcaster.broadcast(new AliasEvent(alias, AliasEvent.Event.DELETE));
|
if(hasAliasList(alias.getAliasListName()))
|
||||||
}
|
{
|
||||||
}
|
AliasList aliasList = getAliasList(alias.getName());
|
||||||
else if(change.wasUpdated())
|
|
||||||
{
|
if(alias != null)
|
||||||
for(int x = change.getFrom(); x < change.getTo(); x++)
|
{
|
||||||
{
|
aliasList.removeAlias(alias);
|
||||||
mAliasEventBroadcaster.broadcast(new AliasEvent(change.getList().get(x), AliasEvent.Event.CHANGE));
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* SDR Trunk
|
|
||||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>
|
|
||||||
******************************************************************************/
|
|
||||||
package io.github.dsheirer.alias.action;
|
|
||||||
|
|
||||||
import io.github.dsheirer.alias.AliasEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for receiving alias events. Each listener will receive
|
|
||||||
* notification of all alias events.
|
|
||||||
*/
|
|
||||||
public interface AliasActionListener
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Notifies the listener that an alias event has occurred
|
|
||||||
*/
|
|
||||||
public void aliasChanged( AliasEvent event );
|
|
||||||
}
|
|
||||||
@@ -74,6 +74,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editor for aliases
|
* Editor for aliases
|
||||||
@@ -97,7 +98,8 @@ public class AliasConfigurationEditor extends SplitPane
|
|||||||
private ComboBox<String> mAliasListNameComboBox;
|
private ComboBox<String> mAliasListNameComboBox;
|
||||||
private Button mNewAliasListButton;
|
private Button mNewAliasListButton;
|
||||||
private FilteredList<Alias> mAliasFilteredList;
|
private FilteredList<Alias> mAliasFilteredList;
|
||||||
private AliasFilterMonitor mAliasFilterMonitor;
|
private SortedList<Alias> mAliasSortedList;
|
||||||
|
private AliasPredicate mAliasPredicate;
|
||||||
|
|
||||||
public AliasConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
public AliasConfigurationEditor(PlaylistManager playlistManager, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
@@ -124,7 +126,6 @@ public class AliasConfigurationEditor extends SplitPane
|
|||||||
*/
|
*/
|
||||||
public void show(Alias alias)
|
public void show(Alias alias)
|
||||||
{
|
{
|
||||||
mLog.debug("Showing: " + alias.getName());
|
|
||||||
if(alias != null)
|
if(alias != null)
|
||||||
{
|
{
|
||||||
String aliasList = alias.getAliasListName();
|
String aliasList = alias.getAliasListName();
|
||||||
@@ -224,20 +225,40 @@ public class AliasConfigurationEditor extends SplitPane
|
|||||||
if(mSearchField == null)
|
if(mSearchField == null)
|
||||||
{
|
{
|
||||||
mSearchField = TextFields.createClearableTextField();
|
mSearchField = TextFields.createClearableTextField();
|
||||||
|
mSearchField.textProperty().addListener((observable, oldValue, newValue) -> update());
|
||||||
}
|
}
|
||||||
|
|
||||||
return mSearchField;
|
return mSearchField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void update()
|
||||||
|
{
|
||||||
|
getAliasFilteredList().setPredicate(null);
|
||||||
|
getAliasPredicate().setAliasListName(getAliasListNameComboBox().getSelectionModel().getSelectedItem());
|
||||||
|
getAliasPredicate().setSearchText(getSearchField().getText());
|
||||||
|
getAliasFilteredList().setPredicate(getAliasPredicate());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AliasPredicate getAliasPredicate()
|
||||||
|
{
|
||||||
|
if(mAliasPredicate == null)
|
||||||
|
{
|
||||||
|
mAliasPredicate = new AliasPredicate();
|
||||||
|
mAliasPredicate.setAliasListName(getAliasListNameComboBox().getSelectionModel().getSelectedItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
return mAliasPredicate;
|
||||||
|
}
|
||||||
|
|
||||||
private ComboBox<String> getAliasListNameComboBox()
|
private ComboBox<String> getAliasListNameComboBox()
|
||||||
{
|
{
|
||||||
if(mAliasListNameComboBox == null)
|
if(mAliasListNameComboBox == null)
|
||||||
{
|
{
|
||||||
mAliasListNameComboBox = new ComboBox<>(mPlaylistManager.getAliasModel().aliasListNames());
|
mAliasListNameComboBox = new ComboBox<>(mPlaylistManager.getAliasModel().aliasListNames());
|
||||||
mAliasListNameComboBox.getSelectionModel().selectedItemProperty()
|
mAliasListNameComboBox.getSelectionModel().selectedItemProperty()
|
||||||
.addListener((observable, oldValue, newValue) -> {
|
.addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
|
||||||
getNewAliasButton().setDisable(newValue == null || newValue.contentEquals(AliasModel.NO_ALIAS_LIST));
|
getNewAliasButton().setDisable(newValue == null || newValue.contentEquals(AliasModel.NO_ALIAS_LIST));
|
||||||
|
update();
|
||||||
});
|
});
|
||||||
|
|
||||||
if(mAliasListNameComboBox.getItems().size() > 1)
|
if(mAliasListNameComboBox.getItems().size() > 1)
|
||||||
@@ -362,15 +383,7 @@ public class AliasConfigurationEditor extends SplitPane
|
|||||||
recordColumn, streamColumn, idsColumn, errorsColumn);
|
recordColumn, streamColumn, idsColumn, errorsColumn);
|
||||||
|
|
||||||
mAliasTableView.setPlaceholder(getPlaceholderLabel());
|
mAliasTableView.setPlaceholder(getPlaceholderLabel());
|
||||||
|
mAliasTableView.setItems(getAliasSortedList());
|
||||||
//Sorting and filtering for the table
|
|
||||||
mAliasFilteredList = new FilteredList<>(mPlaylistManager.getAliasModel().aliasList(),
|
|
||||||
alias -> alias.matchesAliasList(getAliasListNameComboBox().getSelectionModel().getSelectedItem()));
|
|
||||||
mAliasFilterMonitor = new AliasFilterMonitor();
|
|
||||||
|
|
||||||
SortedList<Alias> sortedList = new SortedList<>(mAliasFilteredList);
|
|
||||||
sortedList.comparatorProperty().bind(mAliasTableView.comparatorProperty());
|
|
||||||
mAliasTableView.setItems(sortedList);
|
|
||||||
mAliasTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
mAliasTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||||
mAliasTableView.getSelectionModel().selectedItemProperty()
|
mAliasTableView.getSelectionModel().selectedItemProperty()
|
||||||
.addListener((observable, oldValue, newValue) -> {
|
.addListener((observable, oldValue, newValue) -> {
|
||||||
@@ -381,6 +394,27 @@ public class AliasConfigurationEditor extends SplitPane
|
|||||||
return mAliasTableView;
|
return mAliasTableView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FilteredList<Alias> getAliasFilteredList()
|
||||||
|
{
|
||||||
|
if(mAliasFilteredList == null)
|
||||||
|
{
|
||||||
|
mAliasFilteredList = new FilteredList<>(mPlaylistManager.getAliasModel().aliasList(), getAliasPredicate());
|
||||||
|
}
|
||||||
|
|
||||||
|
return mAliasFilteredList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SortedList<Alias> getAliasSortedList()
|
||||||
|
{
|
||||||
|
if(mAliasSortedList == null)
|
||||||
|
{
|
||||||
|
mAliasSortedList = new SortedList<>(getAliasFilteredList());
|
||||||
|
mAliasSortedList.comparatorProperty().bind(getAliasTableView().comparatorProperty());
|
||||||
|
}
|
||||||
|
|
||||||
|
return mAliasSortedList;
|
||||||
|
}
|
||||||
|
|
||||||
private Label getPlaceholderLabel()
|
private Label getPlaceholderLabel()
|
||||||
{
|
{
|
||||||
if(mPlaceholderLabel == null)
|
if(mPlaceholderLabel == null)
|
||||||
@@ -417,7 +451,7 @@ public class AliasConfigurationEditor extends SplitPane
|
|||||||
mNewAliasButton.setAlignment(Pos.CENTER);
|
mNewAliasButton.setAlignment(Pos.CENTER);
|
||||||
mNewAliasButton.setMaxWidth(Double.MAX_VALUE);
|
mNewAliasButton.setMaxWidth(Double.MAX_VALUE);
|
||||||
mNewAliasButton.setOnAction(event -> {
|
mNewAliasButton.setOnAction(event -> {
|
||||||
Alias alias = new Alias();
|
Alias alias = new Alias("New Alias");
|
||||||
alias.setAliasListName(getAliasListNameComboBox().getSelectionModel().getSelectedItem());
|
alias.setAliasListName(getAliasListNameComboBox().getSelectionModel().getSelectedItem());
|
||||||
mPlaylistManager.getAliasModel().addAlias(alias);
|
mPlaylistManager.getAliasModel().addAlias(alias);
|
||||||
|
|
||||||
@@ -477,7 +511,7 @@ public class AliasConfigurationEditor extends SplitPane
|
|||||||
mCloneAliasButton.setMaxWidth(Double.MAX_VALUE);
|
mCloneAliasButton.setMaxWidth(Double.MAX_VALUE);
|
||||||
mCloneAliasButton.setOnAction(event -> {
|
mCloneAliasButton.setOnAction(event -> {
|
||||||
Alias original = getAliasTableView().getSelectionModel().getSelectedItem();
|
Alias original = getAliasTableView().getSelectionModel().getSelectedItem();
|
||||||
Alias copy = AliasFactory.copyOf(original);
|
Alias copy = AliasFactory.shallowCopyOf(original);
|
||||||
mPlaylistManager.getAliasModel().addAlias(copy);
|
mPlaylistManager.getAliasModel().addAlias(copy);
|
||||||
getAliasTableView().getSelectionModel().clearSelection();
|
getAliasTableView().getSelectionModel().clearSelection();
|
||||||
getAliasTableView().getSelectionModel().select(copy);
|
getAliasTableView().getSelectionModel().select(copy);
|
||||||
@@ -765,47 +799,57 @@ public class AliasConfigurationEditor extends SplitPane
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the filtered set of aliases any time there is a change in the selected alias list name box, or when the
|
* Alias filter predicate
|
||||||
* user types text in the search box.
|
|
||||||
*/
|
*/
|
||||||
public class AliasFilterMonitor
|
public class AliasPredicate implements Predicate<Alias>
|
||||||
{
|
{
|
||||||
public AliasFilterMonitor()
|
private String mAliasListName;
|
||||||
{
|
private String mSearchText;
|
||||||
getAliasListNameComboBox().getSelectionModel().selectedItemProperty()
|
|
||||||
.addListener((observable, oldValue, newValue) -> {
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
getSearchField().textProperty().addListener((observable, oldValue, newValue) -> {
|
@Override
|
||||||
refresh();
|
public boolean test(Alias alias)
|
||||||
});
|
{
|
||||||
|
if(mAliasListName == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(mAliasListName.equals(alias.getAliasListName()))
|
||||||
|
{
|
||||||
|
if(alias.getName() == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(alias.getName().toLowerCase().contains(mSearchText))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(alias.getGroup() != null && alias.getGroup().toLowerCase().contains(mSearchText))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh()
|
public void setAliasListName(String aliasListName)
|
||||||
{
|
{
|
||||||
final String aliasListName = getAliasListNameComboBox().getSelectionModel().getSelectedItem();
|
if(aliasListName != null)
|
||||||
final String filter = getSearchField().getText();
|
{
|
||||||
|
mAliasListName = aliasListName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mAliasFilteredList.setPredicate(alias -> {
|
public void setSearchText(String searchText)
|
||||||
if(filter == null || filter.isEmpty())
|
{
|
||||||
{
|
if(searchText != null)
|
||||||
return alias.matchesAliasList(aliasListName);
|
{
|
||||||
}
|
mSearchText = searchText.toLowerCase();
|
||||||
|
}
|
||||||
String lowerFilter = filter.toLowerCase();
|
else
|
||||||
|
{
|
||||||
if(alias.getName() != null && alias.getName().toLowerCase().contains(lowerFilter))
|
mSearchText = null;
|
||||||
{
|
}
|
||||||
return alias.matchesAliasList(aliasListName);
|
|
||||||
}
|
|
||||||
else if(alias.getGroup() != null && alias.getGroup().toLowerCase().contains(lowerFilter))
|
|
||||||
{
|
|
||||||
return alias.matchesAliasList(aliasListName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -360,49 +359,15 @@ public class AliasItemEditor extends Editor<Alias>
|
|||||||
alias.addAliasID(selected);
|
alias.addAliasID(selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
AliasList aliasList = mPlaylistManager.getAliasModel().getAliasList(alias.getAliasListName());
|
|
||||||
aliasList.removeAlias(alias);
|
|
||||||
|
|
||||||
//Cleanup any alias identifiers that are marked as overlapping. To do this, we remove all of the
|
|
||||||
//affected aliases, reset all of the overlap flags, and then add the aliases back to the alias list.
|
|
||||||
Set<Alias> aliasesToReset = new HashSet<>();
|
|
||||||
for(AliasID aliasID: alias.getAliasIdentifiers())
|
|
||||||
{
|
|
||||||
if(aliasID.overlapProperty().get())
|
|
||||||
{
|
|
||||||
aliasID.overlapProperty().set(false);
|
|
||||||
List<Alias> overlapAliases = aliasList.getOverlappingAliases(alias, aliasID);
|
|
||||||
aliasesToReset.addAll(overlapAliases);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove overlap aliases, reset them, and readd back to the alias list
|
|
||||||
for(Alias resetAlias: aliasesToReset)
|
|
||||||
{
|
|
||||||
aliasList.removeAlias(resetAlias);
|
|
||||||
for(AliasID aliasID: resetAlias.getAliasIdentifiers())
|
|
||||||
{
|
|
||||||
aliasID.setOverlap(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove and replace the remaining non-audio identifiers
|
//Remove and replace the remaining non-audio identifiers
|
||||||
alias.removeNonAudioIdentifiers();
|
alias.removeNonAudioIdentifiers();
|
||||||
|
|
||||||
for(AliasID aliasID: getIdentifiersList().getItems())
|
for(AliasID aliasID: getIdentifiersList().getItems())
|
||||||
{
|
{
|
||||||
aliasID.setOverlap(false);
|
|
||||||
//Create a copy of the identifier so that the alias and the editor don't have the same instance
|
//Create a copy of the identifier so that the alias and the editor don't have the same instance
|
||||||
alias.addAliasID(AliasFactory.copyOf(aliasID));
|
alias.addAliasID(AliasFactory.copyOf(aliasID));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add the aliases back to the alias list
|
|
||||||
for(Alias resetAlias: aliasesToReset)
|
|
||||||
{
|
|
||||||
aliasList.addAlias(resetAlias);
|
|
||||||
}
|
|
||||||
aliasList.addAlias(alias);
|
|
||||||
|
|
||||||
//Remove and replace alias actions
|
//Remove and replace alias actions
|
||||||
alias.removeAllActions();
|
alias.removeAllActions();
|
||||||
for(AliasAction aliasAction: getActionsList().getItems())
|
for(AliasAction aliasAction: getActionsList().getItems())
|
||||||
@@ -411,6 +376,9 @@ public class AliasItemEditor extends Editor<Alias>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AliasList aliasList = mPlaylistManager.getAliasModel().getAliasList(alias.getAliasListName());
|
||||||
|
aliasList.updateAlias(alias);
|
||||||
|
|
||||||
//Reset the alias to refresh the editor.
|
//Reset the alias to refresh the editor.
|
||||||
setItem(alias);
|
setItem(alias);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
package io.github.dsheirer.gui.playlist.alias;
|
package io.github.dsheirer.gui.playlist.alias;
|
||||||
|
|
||||||
import io.github.dsheirer.alias.Alias;
|
import io.github.dsheirer.alias.Alias;
|
||||||
import io.github.dsheirer.alias.AliasEvent;
|
|
||||||
import io.github.dsheirer.alias.AliasModel;
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
@@ -315,7 +314,6 @@ public class AliasViewByRecordingEditor extends VBox
|
|||||||
if(selectedAlias != null)
|
if(selectedAlias != null)
|
||||||
{
|
{
|
||||||
selectedAlias.setRecordable(true);
|
selectedAlias.setRecordable(true);
|
||||||
mPlaylistManager.getAliasModel().broadcast(new AliasEvent(selectedAlias, AliasEvent.Event.CHANGE));
|
|
||||||
updateListFilters();
|
updateListFilters();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -342,7 +340,6 @@ public class AliasViewByRecordingEditor extends VBox
|
|||||||
for(Alias selectedAlias: selectedAliases)
|
for(Alias selectedAlias: selectedAliases)
|
||||||
{
|
{
|
||||||
selectedAlias.setRecordable(true);
|
selectedAlias.setRecordable(true);
|
||||||
mPlaylistManager.getAliasModel().broadcast(new AliasEvent(selectedAlias, AliasEvent.Event.CHANGE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateListFilters();
|
updateListFilters();
|
||||||
@@ -368,7 +365,6 @@ public class AliasViewByRecordingEditor extends VBox
|
|||||||
if(selectedAlias != null)
|
if(selectedAlias != null)
|
||||||
{
|
{
|
||||||
selectedAlias.setRecordable(false);
|
selectedAlias.setRecordable(false);
|
||||||
mPlaylistManager.getAliasModel().broadcast(new AliasEvent(selectedAlias, AliasEvent.Event.CHANGE));
|
|
||||||
updateListFilters();
|
updateListFilters();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -395,7 +391,6 @@ public class AliasViewByRecordingEditor extends VBox
|
|||||||
for(Alias selectedAlias: selectedAliases)
|
for(Alias selectedAlias: selectedAliases)
|
||||||
{
|
{
|
||||||
selectedAlias.setRecordable(false);
|
selectedAlias.setRecordable(false);
|
||||||
mPlaylistManager.getAliasModel().broadcast(new AliasEvent(selectedAlias, AliasEvent.Event.CHANGE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateListFilters();
|
updateListFilters();
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
package io.github.dsheirer.gui.playlist.streaming;
|
package io.github.dsheirer.gui.playlist.streaming;
|
||||||
|
|
||||||
import io.github.dsheirer.alias.Alias;
|
import io.github.dsheirer.alias.Alias;
|
||||||
import io.github.dsheirer.alias.AliasEvent;
|
|
||||||
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
import io.github.dsheirer.alias.id.broadcast.BroadcastChannel;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||||
import io.github.dsheirer.playlist.PlaylistManager;
|
import io.github.dsheirer.playlist.PlaylistManager;
|
||||||
@@ -312,7 +311,6 @@ public class StreamAliasSelectionEditor extends VBox
|
|||||||
if(selectedAlias != null && stream != null)
|
if(selectedAlias != null && stream != null)
|
||||||
{
|
{
|
||||||
selectedAlias.addAliasID(new BroadcastChannel(stream));
|
selectedAlias.addAliasID(new BroadcastChannel(stream));
|
||||||
mPlaylistManager.getAliasModel().broadcast(new AliasEvent(selectedAlias, AliasEvent.Event.CHANGE));
|
|
||||||
updateListFilters();
|
updateListFilters();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -344,7 +342,6 @@ public class StreamAliasSelectionEditor extends VBox
|
|||||||
for(Alias selectedAlias: selectedAliases)
|
for(Alias selectedAlias: selectedAliases)
|
||||||
{
|
{
|
||||||
selectedAlias.addAliasID(new BroadcastChannel(stream));
|
selectedAlias.addAliasID(new BroadcastChannel(stream));
|
||||||
mPlaylistManager.getAliasModel().broadcast(new AliasEvent(selectedAlias, AliasEvent.Event.CHANGE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateListFilters();
|
updateListFilters();
|
||||||
@@ -372,7 +369,6 @@ public class StreamAliasSelectionEditor extends VBox
|
|||||||
if(selectedAlias != null && stream != null)
|
if(selectedAlias != null && stream != null)
|
||||||
{
|
{
|
||||||
selectedAlias.removeBroadcastChannel(stream);
|
selectedAlias.removeBroadcastChannel(stream);
|
||||||
mPlaylistManager.getAliasModel().broadcast(new AliasEvent(selectedAlias, AliasEvent.Event.CHANGE));
|
|
||||||
updateListFilters();
|
updateListFilters();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -400,7 +396,6 @@ public class StreamAliasSelectionEditor extends VBox
|
|||||||
for(Alias selectedAlias: selectedAliases)
|
for(Alias selectedAlias: selectedAliases)
|
||||||
{
|
{
|
||||||
selectedAlias.removeBroadcastChannel(stream);
|
selectedAlias.removeBroadcastChannel(stream);
|
||||||
mPlaylistManager.getAliasModel().broadcast(new AliasEvent(selectedAlias, AliasEvent.Event.CHANGE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateListFilters();
|
updateListFilters();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
|
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
|
||||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||||
|
import io.github.dsheirer.alias.Alias;
|
||||||
import io.github.dsheirer.alias.AliasModel;
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
import io.github.dsheirer.audio.broadcast.BroadcastModel;
|
||||||
import io.github.dsheirer.controller.channel.Channel.ChannelType;
|
import io.github.dsheirer.controller.channel.Channel.ChannelType;
|
||||||
@@ -41,6 +42,7 @@ import io.github.dsheirer.service.radioreference.RadioReference;
|
|||||||
import io.github.dsheirer.source.SourceManager;
|
import io.github.dsheirer.source.SourceManager;
|
||||||
import io.github.dsheirer.source.tuner.TunerModel;
|
import io.github.dsheirer.source.tuner.TunerModel;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -108,10 +110,7 @@ public class PlaylistManager implements Listener<ChannelEvent>
|
|||||||
//save the playlist when there are any changes
|
//save the playlist when there are any changes
|
||||||
mChannelModel.addListener(this);
|
mChannelModel.addListener(this);
|
||||||
|
|
||||||
mAliasModel.addListener(t -> {
|
mAliasModel.aliasList().addListener((ListChangeListener<Alias>)c -> schedulePlaylistSave());
|
||||||
//Save the playlist for all alias events
|
|
||||||
schedulePlaylistSave();
|
|
||||||
});
|
|
||||||
|
|
||||||
mChannelMapModel.addListener(t -> {
|
mChannelMapModel.addListener(t -> {
|
||||||
//Save the playlist for all channel map events
|
//Save the playlist for all channel map events
|
||||||
|
|||||||
Reference in New Issue
Block a user