/*
This file is part of leafdigital leafChat.
leafChat 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.
leafChat 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 leafChat. If not, see <http://www.gnu.org/licenses/>.
Copyright 2012 Samuel Marshall.
*/
package com.leafdigital.ircui;
import java.util.HashSet;
import com.leafdigital.irc.api.IRCPrefs;
import com.leafdigital.prefs.api.*;
import com.leafdigital.ui.api.*;
import com.leafdigital.ui.api.TreeBox.Item;
import leafchat.core.api.*;
/**
* Server preferences page.
*/
@UIHandler({"prefs-server", "addserver"})
public class PrefsServerPage implements TreeBox.DragSingleSelectionHandler,IRCPrefs
{
private Page pThis;
/** UI: Server selector tree view. */
public TreeBox servertreeUI;
/** UI: Add server. */
public Button addUI;
/** UI: Delete server. */
public Button deleteUI;
/** UI: Label warning about global password setting. */
public Label passwordGlobalWarningUI;
/** UI: Auto-identify checkbox. */
public CheckBox autoIdentifyUI;
/** UI: Identify command. */
public EditBox identifyCommandUI;
/**
* UI: Server password.
*/
public EditBox passwordUI;
/**
* UI: Port range.
*/
public EditBox portRangeUI;
/** UI: Security option. */
public Dropdown securityUI;
/** UI: Block containing security option */
public BorderPanel securitySectionUI;
private Dialog addDialog;
/** UI: Add network: Name */
public EditBox addNetworkNameUI;
/** UI: Add network: Suffix */
public EditBox addNetworkSuffixUI;
/** UI: Add server: Address */
public EditBox addServerAddressUI;
/** UI: Add: Add button */
public Button addAddUI;
private boolean networkNameChanged=false;
/** UI: Add: Tabs */
public TabPanel addTabsUI;
/** UI: Choice panel for real server or redirector */
public ChoicePanel categoryUI;
private PluginContext context;
PrefsServerPage(PluginContext context) throws GeneralException
{
UI u = context.getSingle(UI.class);
pThis = u.createPage("prefs-server", this);
this.context = context;
Preferences p=context.getSingle(Preferences.class);
PreferencesGroup group = p.getGroup(p.getPluginOwner(IRCPrefs.IRCPLUGIN_CLASS)).getChild("servers");
rootItem = new PrefsServerItem(group, null, context);
verifyPrefs(group,null);
// Fill security options
securityUI.addValue(PREF_SECUREMODE_NONE, "Unencrypted connection");
securityUI.addValue(PREF_SECUREMODE_OPTIONAL, "Auto-detect");
securityUI.addValue(PREF_SECUREMODE_REQUIRED, "Secure SSL connection");
servertreeUI.setHandler(this);
servertreeUI.select(getRoot());
selected(getRoot());
}
/**
* Makes sure that preferences are valid. If you have no nicknames in root,
* it makes one and sets it default; if you have any DEFAULTNICK settings
* that don't match a NICK setting, these are removed.
* @param pg Group to start with
* @param parentNicks Nicks that are already present in parent groups
*/
private void verifyPrefs(PreferencesGroup pg, HashSet<String> parentNicks)
{
// Get list of nicks valid within this group
HashSet<String> hereNicks =
parentNicks != null
? new HashSet<String>(parentNicks)
: new HashSet<String>();
PreferencesGroup[] apgNicks=pg.getChild(PREFGROUP_NICKS).getAnon();
for(int iNick=0;iNick<apgNicks.length;iNick++)
{
hereNicks.add(apgNicks[iNick].get(PREF_NICK));
}
// If this group's default nick exists and isn't equal to one of the nicks,
// get rid of it. (This should only really be necessary for those upgrading
// from pre-alpha 5 as it shouldn't be possible from now on.)
String defaultNick=pg.get(PREF_DEFAULTNICK,null);
if(defaultNick!=null && !hereNicks.contains(defaultNick))
{
pg.unset(PREF_DEFAULTNICK);
defaultNick=null;
}
// Special handling for root
if(parentNicks==null)
{
// If root doesn't have any nicknames, add a random one
if(hereNicks.isEmpty())
{
String nick="lc"+(Math.random()+"").replaceAll("[^0-9]","");
if(nick.length()>9) nick=nick.substring(0,9);
PreferencesGroup newNick=pg.getChild(PREFGROUP_NICKS).addAnon();
newNick.set(PREF_NICK,nick);
hereNicks.add(nick);
}
if(defaultNick==null)
{
defaultNick=hereNicks.iterator().next();
pg.set(PREF_DEFAULTNICK,defaultNick);
}
// To help those updating from pre-Alpha 5, clear any passwords set at
// root level as these can no longer be set
for(int i=0;i<apgNicks.length;i++)
{
apgNicks[i].unset(PREF_PASSWORD);
}
}
// Recurse to children
PreferencesGroup[] apgChildren=pg.getAnon();
for(int iChild=0;iChild<apgChildren.length;iChild++)
{
verifyPrefs(apgChildren[iChild],hereNicks);
}
}
Page getPage() { return pThis; }
PrefsServerItem rootItem;
@Override
public Item getRoot()
{
return rootItem;
}
@Override
public boolean isRootDisplayed()
{
return true;
}
private PreferencesGroup selectedGroup;
private PrefsServerItem selectedItem;
private final static int COLUMN_NICK=0,COLUMN_PASSWORD=1,COLUMN_DEFAULT=2;
@Override
public void selected(Item i)
{
try
{
PrefsServerItem pi=(PrefsServerItem)i;
selectedGroup=pi==null ? null : pi.getGroup();
selectedItem=pi;
if (selectedGroup != null &&
selectedGroup.getAnonHierarchical(PREF_REDIRECTOR, "no").equals("yes"))
{
categoryUI.display("redirector");
}
else
{
categoryUI.display("realserver");
}
Table tNick=(Table)pThis.getWidget("nicknames");
EditBox ebUser=(EditBox)pThis.getWidget("serveruser");
EditBox ebRealName=(EditBox)pThis.getWidget("serverrealname");
EditBox ebQuitMessage=(EditBox)pThis.getWidget("serverquitmessage");
// Clear nick table
while(tNick.getNumItems()>0)
{
tNick.removeItem(0);
}
deleteUI.setEnabled(selectedGroup!=null && selectedGroup!=rootItem.getGroup());
addUI.setEnabled(selectedGroup!=null);
if(selectedGroup==null)
{
ebUser.setValue("");
ebUser.setEnabled(false);
ebRealName.setValue("");
ebRealName.setEnabled(false);
ebQuitMessage.setValue("");
ebQuitMessage.setEnabled(false);
identifyCommandUI.setValue("");
identifyCommandUI.setEnabled(false);
autoIdentifyUI.setEnabled(false);
passwordUI.setValue("");
passwordUI.setEnabled(false);
portRangeUI.setValue("");
portRangeUI.setEnabled(false);
securitySectionUI.setVisible(false);
}
else
{
fillNickTable(tNick,selectedGroup,true);
passwordGlobalWarningUI.setVisible(i==rootItem);
ebUser.setValue(
selectedGroup.getAnonHierarchical(PREF_USER,PREFDEFAULT_USER)
);
ebUser.setEnabled(true);
changeUser();
ebRealName.setValue(
selectedGroup.getAnonHierarchical(PREF_REALNAME,PREFDEFAULT_REALNAME)
);
ebRealName.setEnabled(true);
changeRealName();
ebQuitMessage.setValue(
selectedGroup.getAnonHierarchical(PREF_QUITMESSAGE,PREFDEFAULT_QUITMESSAGE)
);
ebQuitMessage.setEnabled(true);
changeQuitMessage();
identifyCommandUI.setValue(
selectedGroup.getAnonHierarchical(PREF_IDENTIFYPATTERN,PREFDEFAULT_IDENTIFYPATTERN)
);
identifyCommandUI.setEnabled(true);
changeIdentifyCommand();
autoIdentifyUI.setChecked(
selectedGroup.getAnonHierarchical(PREF_AUTOIDENTIFY,"y").equals("y"));
autoIdentifyUI.setEnabled(true);
changeAutoIdentify();
passwordUI.setValue(
selectedGroup.getAnonHierarchical(PREF_SERVERPASSWORD,""));
passwordUI.setEnabled(true);
changePassword();
portRangeUI.setValue(
selectedGroup.getAnonHierarchical(PREF_PORTRANGE,""));
portRangeUI.setEnabled(true);
changePortRange();
if(pi.isServer())
{
securitySectionUI.setVisible(true);
String secureMode = selectedGroup.get(PREF_SECUREMODE, PREFDEFAULT_SECUREMODE);
securityUI.setSelected(secureMode);
}
else
{
securitySectionUI.setVisible(false);
}
}
}
catch(GeneralException ge)
{
throw new Error("bugger",ge);
}
}
private void fillNickTable(Table t,PreferencesGroup pg,boolean bCurrent)
{
// Do parent first
PreferencesGroup pgParent=pg.getAnonParent();
if(pgParent!=null) fillNickTable(t,pgParent,false);
// Add entries from this group
PreferencesGroup[] apgNicks=pg.getChild(PREFGROUP_NICKS).getAnon();
entryloop: for(int iEntry=0;iEntry<apgNicks.length;iEntry++)
{
String
sNick=apgNicks[iEntry].get(PREF_NICK),
sPassword=apgNicks[iEntry].get(PREF_PASSWORD,"");
// See if row already exists
for(int iRow=0;iRow<t.getNumItems();iRow++)
{
if(t.getString(iRow,COLUMN_NICK).equals(sNick))
{
// Just set the password
t.setString(iRow,COLUMN_PASSWORD,sPassword);
if(bCurrent) t.setDim(iRow,COLUMN_PASSWORD,false);
// Bail to next entry
continue entryloop;
}
}
// OK, need new row
int iNewRow=t.addItem();
t.setString(iNewRow,COLUMN_NICK,sNick);
t.setString(iNewRow,COLUMN_PASSWORD,sPassword);
t.setEditable(iNewRow,COLUMN_PASSWORD,selectedItem!=rootItem);
if(!bCurrent)
{
t.setEditable(iNewRow,COLUMN_NICK,false);
t.setDim(iNewRow,COLUMN_PASSWORD,true);
}
}
// If this is the current group, set the default column too
if(bCurrent)
{
// Get hierarchical default
String sDefault=pg.getAnonHierarchical(PREF_DEFAULTNICK,null);
// Find default and set it
boolean bFound=false;
for(int iRow=0;iRow<t.getNumItems();iRow++)
{
if(t.getString(iRow,COLUMN_NICK).equals(sDefault))
{
t.setBoolean(iRow,COLUMN_DEFAULT,true);
bFound=true;
}
}
// If no default, use the first one
if(!bFound && t.getNumItems()>0) t.setBoolean(0,COLUMN_DEFAULT,true);
// Add extra row for people to type new ones
addNickTableRow();
}
}
/**
* Action: Nickname selected.
* @throws GeneralException Any error
*/
@UIAction
public void nicknamesSelect() throws GeneralException
{
Table t=(Table)pThis.getWidget("nicknames");
Button bDelete=(Button)pThis.getWidget("nicknamesdelete");
int iRow=t.getSelectedIndex();
if(iRow==Table.NONE)
{
bDelete.setEnabled(false);
}
else
{
bDelete.setEnabled(
t.isEditable(iRow,COLUMN_NICK) && !t.isOverwrite(iRow,COLUMN_NICK) &&
t.getNumItems()>2); // 2 because of the 'add new nick' thing
}
}
/**
* Action: Nickname deleted.
* @throws GeneralException Any error
*/
@UIAction
public void nicknamesDelete() throws GeneralException
{
// Get table
Table t=(Table)pThis.getWidget("nicknames");
int iIndex=t.getSelectedIndex();
// Delete from prefs
deleteNick(selectedGroup,t.getString(iIndex,COLUMN_NICK));
// Delete from table
if(t.getBoolean(iIndex,COLUMN_DEFAULT))
{
// Something else is default now, set it
String defaultNick=selectedGroup.getAnonHierarchical(PREF_DEFAULTNICK);
for(int i=0;i<t.getNumItems();i++)
{
if(t.getString(i,COLUMN_NICK).equals(defaultNick))
{
t.setBoolean(i,COLUMN_DEFAULT,true);
break;
}
}
}
// Remove item from table
t.removeItem(iIndex);
}
private void deleteNick(PreferencesGroup pg,String sNick)
{
PreferencesGroup[] apgNicks=pg.getChild(PREFGROUP_NICKS).getAnon();
// Delete in this group if present
String firstOtherNick=null;
for(int iNick=0;iNick<apgNicks.length;iNick++)
{
if(apgNicks[iNick].get(PREF_NICK).equals(sNick))
apgNicks[iNick].remove();
else if(firstOtherNick==null)
firstOtherNick=apgNicks[iNick].get(PREF_NICK);
}
String defaultNick=pg.get(PREF_DEFAULTNICK,null);
if(defaultNick!=null && defaultNick.equals(sNick))
{
if(pg.getAnonParent()==null)
{
// Root must have default nick
pg.set(PREF_DEFAULTNICK,firstOtherNick);
}
else
{
// Use parent's default nick
pg.unset(PREF_DEFAULTNICK);
}
}
// Delete from all child groups
PreferencesGroup[] apgChildren=pg.getAnon();
for(int iChild=0;iChild<apgChildren.length;iChild++)
{
deleteNick(apgChildren[iChild],sNick);
}
}
/**
* Action: Nickname option changed.
* @param index Row
* @param col Column
* @param before Previous value
* @throws GeneralException Any error
*/
@UIAction
public void nicknamesChange(int index,int col,Object before) throws GeneralException
{
Table t=(Table)pThis.getWidget("nicknames");
PreferencesGroup pgParent=selectedGroup.getAnonParent();
switch(col)
{
case COLUMN_NICK: // Nickname
{
if(index==t.getNumItems()-1) // Last row = adding item
{
// Store in prefs
PreferencesGroup pgNew=selectedGroup.getChild(PREFGROUP_NICKS).addAnon();
pgNew.set(PREF_NICK,t.getString(index,col));
// Update this row to make it 'normal'
t.setOverwrite(index,COLUMN_NICK,false);
t.setEditable(index,COLUMN_PASSWORD,pgParent!=null);
t.setEditable(index,COLUMN_DEFAULT,true);
// Add new row for adding more nicks
addNickTableRow();
nicknamesSelect(); // Selected row might be deletable
}
else // Changing existing nick
{
changeNick(selectedGroup,(String)before,t.getString(index,col));
}
} break;
case COLUMN_PASSWORD: // Password
{
PreferencesGroup[] apgNicks=selectedGroup.getChild(PREFGROUP_NICKS).getAnon();
String sNick=t.getString(index,COLUMN_NICK),sPassword=t.getString(index,COLUMN_PASSWORD);
boolean bSameAsParent=pgParent!=null && sPassword.equals(getNickPassword(pgParent,sNick));
// Edit in this group if we've got it
boolean bFound=false;
for(int iNick=0;iNick<apgNicks.length;iNick++)
{
if(apgNicks[iNick].get(PREF_NICK).equals(sNick))
{
bFound=true;
// Does that password match one from a parent? If so, don't store it
// separately. Also delete if it's blank now
if(bSameAsParent)
{
apgNicks[iNick].remove();
}
else if(pgParent==null && sPassword.equals(""))
{
apgNicks[iNick].unset(PREF_PASSWORD);
}
else
{
apgNicks[iNick].set(PREF_PASSWORD,sPassword);
}
break;
}
}
// Not got it? Add new record
if(!bFound && !sPassword.equals(""))
{
PreferencesGroup pgNew=selectedGroup.getChild(PREFGROUP_NICKS).addAnon();
pgNew.set(PREF_NICK,sNick);
pgNew.set(PREF_PASSWORD,sPassword);
}
resolvePasswords(selectedGroup,sNick,sPassword,true);
t.setDim(index,col,bSameAsParent);
} break;
case COLUMN_DEFAULT: // Default
{
// Don't let them turn the top one off (sigh, these should be radios)
if(!t.getBoolean(index,col))
{
t.setBoolean(index,col,true);
}
else
{
// Turn all the others off
for(int iItem=0;iItem<t.getNumItems();iItem++)
{
if(iItem!=index) t.setBoolean(iItem,col,false);
}
// Set in prefs
String sNick=t.getString(index,COLUMN_NICK);
if(pgParent==null)
{
selectedGroup.set(PREF_DEFAULTNICK,sNick);
}
else if (sNick.equals(pgParent.getAnonHierarchical(PREF_DEFAULTNICK,null)))
{
selectedGroup.unset(PREF_DEFAULTNICK);
}
else
{
selectedGroup.set(PREF_DEFAULTNICK,sNick);
}
}
} break;
default:
assert false;
}
}
/**
* Get rid of any entries that refer to this nick but have the same password.
* @param pg Group
* @param nick Nickname
* @param password Password
* @param childrenOnly True to apply only to children not this group itself
* @throws BugException System bug
*/
private void resolvePasswords(PreferencesGroup pg,String nick,String password,boolean childrenOnly)
throws BugException
{
if(!childrenOnly)
{
// Apply change to this group
PreferencesGroup[] apgNicks=pg.getChild(PREFGROUP_NICKS).getAnon();
for(int iNick=0;iNick<apgNicks.length;iNick++)
{
if(apgNicks[iNick].get(PREF_NICK).equals(nick))
{
if(apgNicks[iNick].get(PREF_PASSWORD,"").equals(password))
apgNicks[iNick].remove();
break;
}
}
}
// Apply change to children
PreferencesGroup[] apgChildren=pg.getAnon();
for(int iChild=0;iChild<apgChildren.length;iChild++)
{
resolvePasswords(apgChildren[iChild],nick,password,false);
}
}
/**
* Obtains nickname password starting from a particular group (checking its parents too).
* @param pg Group to start from
* @param nick Nickname in question
* @return Password or "" if none
* @throws BugException
*/
private String getNickPassword(PreferencesGroup pg,String nick)
{
PreferencesGroup[] apgNicks=pg.getChild(PREFGROUP_NICKS).getAnon();
// Edit in this group if we've got it
for(int iNick=0;iNick<apgNicks.length;iNick++)
{
if(apgNicks[iNick].get(PREF_NICK).equals(nick))
{
String sPassword=apgNicks[iNick].get(PREF_PASSWORD,"");
return sPassword;
}
}
// OK try parent
PreferencesGroup pgParent=pg.getAnonParent();
if(pgParent==null)
return "";
else
return getNickPassword(pgParent,nick);
}
/**
* Changes a nickname in preferences, including all child references to it.
* @param pg Root group
* @param sBefore Previous nick
* @param sAfter New nick
* @throws GeneralException Any error
*/
static void changeNick(PreferencesGroup pg,String sBefore,String sAfter) throws GeneralException
{
// Apply change to nick if stored in this group
PreferencesGroup[] apgNicks=pg.getChild(PREFGROUP_NICKS).getAnon();
for(int iNick=0;iNick<apgNicks.length;iNick++)
{
if(apgNicks[iNick].get(PREF_NICK).equals(sBefore))
{
apgNicks[iNick].set(PREF_NICK,sAfter);
break;
}
}
// If this group's default nick is the 'before' one, change it
if(pg.get(PREF_DEFAULTNICK,"").equals(sBefore))
pg.set(PREF_DEFAULTNICK,sAfter);
// Apply change to children
PreferencesGroup[] apgChildren=pg.getAnon();
for(int iChild=0;iChild<apgChildren.length;iChild++)
{
changeNick(apgChildren[iChild],sBefore,sAfter);
}
}
/**
* User makes change to nickname or password field.
* @param index Index in table
* @param col Column
* @param value New value
* @param ec Editing control interface
* @throws GeneralException Any error
*/
@UIAction
public void nicknamesEditing(int index,int col,String value,Table.EditingControl ec) throws GeneralException
{
Table t=(Table)pThis.getWidget("nicknames");
switch(col)
{
case COLUMN_NICK:
{
// Check nick is one of the permitted patterns
if(!value.matches("[A-Za-z_\\[\\]\\\\`^{}][A-Za-z0-9-_\\[\\]\\\\`^{}]*"))
{
ec.markError();
return;
}
// Check it's not the same as another nick
for(int iRow=0;iRow<t.getNumItems();iRow++)
{
if(iRow!=index && t.getString(iRow,COLUMN_NICK).equals(value))
{
ec.markError();
return;
}
}
} break;
case COLUMN_PASSWORD:
{
if(!value.matches("\\S*"))
{
ec.markError();
return;
}
PreferencesGroup pgParent=selectedGroup.getAnonParent();
if(pgParent!=null && getNickPassword(pgParent,t.getString(index,COLUMN_NICK)).equals(value))
{
ec.markDim();
return;
}
}
default:
assert false;
}
}
private final static String ADDNICKTEXT="(Add new...)";
private void addNickTableRow()
{
Table tNick=(Table)pThis.getWidget("nicknames");
int iNew=tNick.addItem();
tNick.setString(iNew,COLUMN_NICK,ADDNICKTEXT);
tNick.setOverwrite(iNew,COLUMN_NICK,true);
tNick.setEditable(iNew,COLUMN_PASSWORD,false);
tNick.setEditable(iNew,COLUMN_DEFAULT,false);
}
// public void changeNick() throws GeneralException
// {
// EditBox ebNick=(EditBox)pThis.getWidget("servernick");
// String sValue=ebNick.getValue();
//
// String sParentValue=pgSelected.getAnonHierarchical(PREF_NICK,PREFDEFAULT_NICK,false);
//
// if(sValue.equals(sParentValue))
// {
// pgSelected.unset(PREF_NICK);
// ebNick.setFlag(EditBox.FLAG_DIM);
// }
// else if(sValue.matches("[A-Za-z][]A-Za-z0-9\\[\\\\`^{}-]*")) // From RFC sect 2.3.1
// {
// pgSelected.set(PREF_NICK,sValue);
// ebNick.setFlag(EditBox.FLAG_NORMAL);
// }
// else
// {
// // Don't save
// ebNick.setFlag(EditBox.FLAG_ERROR);
// }
// }
/**
* Action: Username changed.
* @throws GeneralException Any error
*/
@UIAction
public void changeUser() throws GeneralException
{
EditBox eb=(EditBox)pThis.getWidget("serveruser");
String sValue=eb.getValue();
String sParentValue=selectedGroup.getAnonHierarchical(PREF_USER,PREFDEFAULT_USER,false);
if(sValue.equals(sParentValue))
{
selectedGroup.unset(PREF_USER);
eb.setFlag(EditBox.FLAG_DIM);
}
else if(sValue.matches("[^ \r\n\0]+")) // From RFC sect 2.3.1
{
selectedGroup.set(PREF_USER,sValue);
eb.setFlag(EditBox.FLAG_NORMAL);
}
else
{
// Don't save
eb.setFlag(EditBox.FLAG_ERROR);
}
}
/**
* Action: Realname changed.
* @throws GeneralException Any error
*/
@UIAction
public void changeRealName() throws GeneralException
{
EditBox eb=(EditBox)pThis.getWidget("serverrealname");
String sValue=eb.getValue();
String sParentValue=selectedGroup.getAnonHierarchical(PREF_REALNAME,PREFDEFAULT_REALNAME,false);
if(sValue.equals(sParentValue))
{
selectedGroup.unset(PREF_REALNAME);
eb.setFlag(EditBox.FLAG_DIM);
}
else if(sValue.length()>0)
{
selectedGroup.set(PREF_REALNAME,sValue);
eb.setFlag(EditBox.FLAG_NORMAL);
}
else
{
// Don't save
eb.setFlag(EditBox.FLAG_ERROR);
}
}
/**
* Action: Quit message changed.
* @throws GeneralException Any error
*/
@UIAction
public void changeQuitMessage() throws GeneralException
{
EditBox eb=(EditBox)pThis.getWidget("serverquitmessage");
String sValue=eb.getValue();
String sParentValue=selectedGroup.getAnonHierarchical(PREF_QUITMESSAGE,PREFDEFAULT_QUITMESSAGE,false);
if(sValue.equals(sParentValue))
{
selectedGroup.unset(PREF_QUITMESSAGE);
eb.setFlag(EditBox.FLAG_DIM);
}
else
{
selectedGroup.set(PREF_QUITMESSAGE,sValue);
eb.setFlag(EditBox.FLAG_NORMAL);
}
}
/**
* Action: Identify command changed.
* @throws GeneralException Any error
*/
@UIAction
public void changeIdentifyCommand() throws GeneralException
{
String sValue=identifyCommandUI.getValue();
String sParentValue=selectedGroup.getAnonHierarchical(PREF_IDENTIFYPATTERN,PREFDEFAULT_IDENTIFYPATTERN,false);
if(sValue.equals(sParentValue))
{
selectedGroup.unset(PREF_IDENTIFYPATTERN);
identifyCommandUI.setFlag(EditBox.FLAG_DIM);
}
else if(sValue.matches("/[a-z]+.*"))
{
selectedGroup.set(PREF_IDENTIFYPATTERN,sValue);
identifyCommandUI.setFlag(EditBox.FLAG_NORMAL);
}
else
{
// Don't save
identifyCommandUI.setFlag(EditBox.FLAG_ERROR);
}
}
/**
* Action: Auto-identify option changed.
* @throws GeneralException Any error
*/
@UIAction
public void changeAutoIdentify() throws GeneralException
{
String sValue=autoIdentifyUI.isChecked() ? "y" : "n";
String sParentValue=selectedGroup.getAnonHierarchical(IRCPrefs.PREF_AUTOIDENTIFY,"y",false);
if(sValue.equals(sParentValue))
{
selectedGroup.unset(IRCPrefs.PREF_AUTOIDENTIFY);
}
else
{
selectedGroup.set(IRCPrefs.PREF_AUTOIDENTIFY,sValue);
}
identifyCommandUI.setEnabled(autoIdentifyUI.isChecked());
}
@Override
public boolean canDrag(Item i)
{
return i!=rootItem;
}
@Override
public boolean canDragTo(Item moving,Item parent,int parentPos)
{
if(((PrefsServerItem)moving).isNetwork())
{
// Can't drag networks into networks
return parent==rootItem;
}
else
{
return true;
}
}
@Override
public void dragTo(Item moving,Item parent,int parentPos)
{
((PrefsServerItem)moving).moveTo((PrefsServerItem)parent,parentPos);
servertreeUI.update();
selected(moving);
}
/**
* Action: Add button.
*/
@UIAction
public void actionAdd()
{
UI ui = context.getSingle(UI.class);
addDialog = ui.createDialog("addserver", this);
addDialog.show(pThis.getOwner());
}
/**
* Action: User clicks Add within Add dialog.
*/
@UIAction
public void actionAddAdd()
{
PrefsServerItem newItem;
if(addTabsUI.getDisplayed().equals("addNetworkPage"))
{
PreferencesGroup newNetwork=rootItem.getGroup().addAnon();
newNetwork.set(IRCPrefs.PREF_NETWORK,addNetworkNameUI.getValue());
newNetwork.set(IRCPrefs.PREF_NETWORKSUFFIX,addNetworkSuffixUI.getValue());
newNetwork.set(IRCPrefs.PREF_HANDADDED,"yes");
newItem = new PrefsServerItem(newNetwork, rootItem, context);
rootItem.addItemOnly(newItem);
}
else
{
PrefsServerItem parent=selectedItem;
while(parent!=null && parent.isServer()) parent=(PrefsServerItem)parent.getParent();
if(parent==null) parent=rootItem;
PreferencesGroup newServer=parent.getGroup().addAnon();
newServer.set(IRCPrefs.PREF_HOST,addServerAddressUI.getValue());
newServer.set(IRCPrefs.PREF_HANDADDED,"yes");
newItem = new PrefsServerItem(newServer, parent, context);
parent.addItemOnly(newItem);
}
servertreeUI.update();
servertreeUI.select(newItem);
selected(newItem);
addDialog.close();
}
/**
* Action: User clicks Cancel within Add dialog.
*/
@UIAction
public void actionAddCancel()
{
addDialog.close();
}
private void enableAddButton()
{
if(addTabsUI.getDisplayed().equals("addNetworkPage"))
{
addAddUI.setEnabled(
addNetworkSuffixUI.getFlag() == EditBox.FLAG_NORMAL &&
addNetworkSuffixUI.getValue().length() > 0 &&
addNetworkNameUI.getValue().length() > 0);
}
else
{
addAddUI.setEnabled(addServerAddressUI.getFlag()==EditBox.FLAG_NORMAL &&
addServerAddressUI.getValue().length()>0);
}
}
/**
* Action: User changes tabs in Add dialog.
*/
@UIAction
public void changeAddTabs()
{
enableAddButton();
}
/**
* Action: User changes network suffix in Add dialog.
*/
@UIAction
public void changeAddNetworkSuffix()
{
String text=addNetworkSuffixUI.getValue();
if(text.matches("([a-z0-9-][a-z0-9.-]*)?"))
{
if(!networkNameChanged || addNetworkNameUI.getValue().length()==0)
{
addNetworkNameUI.setValue(text);
networkNameChanged=false;
}
addNetworkSuffixUI.setFlag(EditBox.FLAG_NORMAL);
}
else
{
addNetworkSuffixUI.setFlag(EditBox.FLAG_ERROR);
}
enableAddButton();
}
/**
* Action: User changes network name in Add dialog.
*/
@UIAction
public void changeAddNetworkName()
{
networkNameChanged=true;
}
/**
* Action: User changes server address in Add dialog.
*/
@UIAction
public void changeAddServerAddress()
{
String text=addServerAddressUI.getValue();
if(text.matches("[a-z0-9.-]*"))
{
addServerAddressUI.setFlag(EditBox.FLAG_NORMAL);
}
else
{
addServerAddressUI.setFlag(EditBox.FLAG_ERROR);
}
enableAddButton();
}
/**
* Action: User closes Add dialog.
*/
@UIAction
public void closedAdd()
{
addDialog=null;
}
/**
* Action: User clicks Delete.
*/
@UIAction
public void actionDelete()
{
String network=selectedGroup.get(IRCPrefs.PREF_NETWORK,null);
String server=selectedGroup.get(IRCPrefs.PREF_HOST,null);
UI ui=context.getSingle(UI.class);
if(ui.showQuestion(pThis,"Confirm delete",
network!=null ?
"Are you sure you want to delete preferences for the network "+network+
", including all servers within it?"
: "Are you sure you want to delete preferences for the server "+server+"?",
UI.BUTTON_YES|UI.BUTTON_CANCEL,null,null,null,UI.BUTTON_CANCEL)==UI.BUTTON_YES)
{
selectedItem.remove();
servertreeUI.update();
servertreeUI.select(rootItem);
selected(rootItem);
}
}
/**
* Action: User changes port range.
*/
@UIAction
public void changePortRange()
{
String sValue=portRangeUI.getValue();
String sParentValue=selectedGroup.getAnonHierarchical(PREF_PORTRANGE,PREFDEFAULT_PORTRANGE,false);
if(sValue.equals(sParentValue))
{
selectedGroup.unset(PREF_PORTRANGE);
portRangeUI.setFlag(EditBox.FLAG_DIM);
}
else if(sValue.matches("[0-9]+(-[0-9]+)?"))
{
selectedGroup.set(PREF_PORTRANGE,sValue);
portRangeUI.setFlag(EditBox.FLAG_NORMAL);
}
else
{
portRangeUI.setFlag(EditBox.FLAG_ERROR);
}
}
/**
* Action: User changes server password.
*/
@UIAction
public void changePassword()
{
String sValue=passwordUI.getValue();
String sParentValue=selectedGroup.getAnonHierarchical(PREF_SERVERPASSWORD,PREFDEFAULT_SERVERPASSWORD,false);
if(sValue.equals(sParentValue))
{
selectedGroup.unset(PREF_SERVERPASSWORD);
passwordUI.setFlag(EditBox.FLAG_DIM);
}
else if(sValue.matches("[^ ]*"))
{
selectedGroup.set(PREF_SERVERPASSWORD,sValue);
passwordUI.setFlag(EditBox.FLAG_NORMAL);
}
else
{
passwordUI.setFlag(EditBox.FLAG_ERROR);
}
}
/**
* Action: User changes security option.
*/
@UIAction
public void changeSecurity()
{
String value = (String)securityUI.getSelected();
selectedGroup.set(PREF_SECUREMODE, value);
}
}