/**
* Copyright (c) 2010 Marc A. Paradise This file is part of "BBSSH" BBSSH is based upon MidpSSH by Karl von Randow.
* MidpSSH was based upon Telnet Floyd and FloydSSH by Radek Polak. 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 2 of the License, or (at your option) any later version. This program is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
* Cambridge, MA 02139, USA.
*/
package org.bbssh.ui.screens;
import java.util.Vector;
import net.rim.device.api.applicationcontrol.ApplicationPermissions;
import net.rim.device.api.i18n.ResourceBundle;
import net.rim.device.api.i18n.ResourceBundleFamily;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.component.Status;
import net.rim.device.api.ui.container.MainScreen;
import org.bbssh.BBSSHApp;
import org.bbssh.help.HelpManager;
import org.bbssh.i18n.BBSSHResource;
import org.bbssh.model.ConnectionManager;
import org.bbssh.model.ConnectionProperties;
import org.bbssh.model.KeyBindingManager;
import org.bbssh.model.Settings;
import org.bbssh.model.SettingsManager;
import org.bbssh.net.ConnectionHelper;
import org.bbssh.patterns.UpdatingBackgroundTask;
import org.bbssh.platform.PlatformServicesProvider;
import org.bbssh.session.RemoteSessionInstance;
import org.bbssh.session.SessionManager;
import org.bbssh.ui.components.ConnectionListfieldCallback;
import org.bbssh.ui.components.HeaderBar;
import org.bbssh.ui.components.MemoryDialog;
import org.bbssh.ui.components.PleaseWaitTaskMonitorScreen;
import org.bbssh.ui.screens.macros.MacroManagerScreen;
import org.bbssh.util.Logger;
import org.bbssh.util.Tools;
import org.bbssh.util.Version;
/**
* From this screen user can launch or open an session, or proceed to various configuration screens.
*/
public class PrimaryScreen extends MainScreen {
ResourceBundleFamily res = ResourceBundle.getBundle(BBSSHResource.BUNDLE_ID, BBSSHResource.BUNDLE_NAME);
protected ListField sessions;
private ConnectionInstancePropertiesScreen curDetailScreen;
/** Session state management: 0x100000 */
private final MenuItem sessionConnect = new MenuItem(res, BBSSHResource.MENU_CONNECT, 0x00100000, 0) {
public void run() {
handleConnectSession();
}
};
private final MenuItem sessionResume = new MenuItem(res, BBSSHResource.MENU_RESUME, 0x00100000, 5) {
public void run() {
handleResumeOrConnectSession();
}
};
private final MenuItem sessionReconnect = new MenuItem(res, BBSSHResource.MENU_RECONNECT, 0x00100000, 5) {
public void run() {
handleReconnectSession();
}
};
MenuItem sessionDisconnect = new MenuItem(res, BBSSHResource.MENU_DISCONNECT, 0x00100000, 10) {
public void run() {
int node = sessions.getSelectedIndex();
if (node > -1) {
SessionManager.getInstance().disconnectSession(getSelectedRemoteSessionInstance());
refreshConnections();
}
}
};
MenuItem sessionTerminate = new MenuItem(res, BBSSHResource.MENU_CLOSE_SESSION, 0x00100000, 15) {
public void run() {
int node = sessions.getSelectedIndex();
if (node > -1) {
SessionManager.getInstance().terminateSession(getSelectedRemoteSessionInstance());
}
}
};
/** Connection Definition management: 0x200000 */
private final MenuItem connectionCreateNew = new MenuItem(res, BBSSHResource.MENU_NEW_CONNECTION, 0x00200010, 1) {
public void run() {
showSessionDetailScreen(true);
}
};
private final MenuItem connectionEdit = new MenuItem(res, BBSSHResource.MENU_EDIT_CONNECTION, 0x00200020, 2) {
public void run() {
showSessionDetailScreen(false);
}
};
private final MenuItem connectionDuplicate = new MenuItem(res, BBSSHResource.MENU_DUPLICATE, 0x00200030, 3) {
public void run() {
handleDuplicateSession();
}
};
private final MenuItem connectionDelete = new MenuItem(res, BBSSHResource.MENU_DELETE_CONNECTION, 0x00200040, 4) {
public void run() {
handleDeleteCurrentSession();
}
};
// User-configurable components - 0x00300000
private final MenuItem keyManager = new MenuItem(res, BBSSHResource.MENU_KEY_MANAGER, 0x00300000, 0) {
public void run() {
UiApplication.getUiApplication().pushScreen(new KeyManagerScreen());
}
};
private final MenuItem keyBindMenu = new MenuItem(res, BBSSHResource.MENU_KEYBINDINGS, 0x00300010, 1) {
public void run() {
UiApplication.getUiApplication().pushScreen(new KeybindingScreen());
}
};
private final MenuItem macrosMenu = new MenuItem(res, BBSSHResource.MENU_MACROS, 0x00300020, 2) {
public void run() {
UiApplication.getUiApplication().pushScreen(new MacroManagerScreen());
}
};
private final MenuItem settingsMenu = new MenuItem(res, BBSSHResource.MENU_SETTINGS, 0x00300030, 3) {
public void run() {
UiApplication.getUiApplication().pushScreen(new SettingsScreen());
}
};
// Help and feedback: 0x00500000
private final MenuItem aboutMenu = new MenuItem(res, BBSSHResource.MENU_ABOUT, 0x00500000, 0) {
public void run() {
UiApplication.getUiApplication().pushScreen(new AboutScreen());
}
};
private final MenuItem sendFeedback = new MenuItem(res, BBSSHResource.MENU_SEND_FEEDBACK, 0x00500010, 1) {
public void run() {
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
Tools.sendFeedback(null);
}
});
}
};
private boolean forceClose;
/**
* Instantiates a new primary screen.
*/
public PrimaryScreen() {
super(DEFAULT_MENU | DEFAULT_CLOSE);
// Note that subclass of PrimaryScreen will implement proper enhanced
// titlebar (6.0)
if (!PlatformServicesProvider.getInstance().isEnhancedTitlebarSupported()) {
HeaderBar title = new HeaderBar(res.getString(BBSSHResource.TITLE_CONNECTIONS));
title.setBackgroundColor(0);
title.setFontColor(0xFFFFFF);
title.setDrawSeparator(false);
setTitle(title);
}
sessions = new ListField();
// Okay, this is pointless - the intiialziation dialog has to run later,
// because otherwise we're pushing it onto the stack before teh event
// dispatcher has
// started. But if we're running it later, we're actually already runing
// it too late to
// be useful...
// UiApplication.getUiApplication().invokeLater(new Runnable() {
// public void run() {
// waitForInitialiation();
// }
// });
// No time to look now, but the internal call in psp constrcutor doesn't
// seem to always get called...
PlatformServicesProvider.getInstance().determineLayout();
sessions = new ListField(BBSSHResource.ABOUT_MENU_CHECK_UPDATES_NOW);
// = new TreeField(new ConnectionListCallback(), TreeField.FOCUSABLE);
sessions.setEmptyString(res.getString(BBSSHResource.INFO_PRIMARY_NO_CONNECTION_DEFINED), DrawStyle.HCENTER);
ConnectionListfieldCallback cb = new ConnectionListfieldCallback(false);
sessions.setRowHeight(cb.getRowHeight());
sessions.setCallback(cb);
populateConnectionList();
add(sessions);
performBackgroundUpdateCheck();
// do this later - otherwise we try to push the dialogs onto the display
// before the event loop starts.
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
showStartupDialogs();
}
});
}
private void populateConnectionList() {
sessions.setSize(ConnectionManager.getInstance().getConnections().size());
sessions.invalidate();
}
/**
* Waits for background load of startup data to be completed.
*/
// private void waitForInitialiation() {
// Logger.info("PrimaryScreen waiting for initialization.");
// PleaseWaitTaskMonitorScreen wait = new PleaseWaitTaskMonitorScreen(new
// UpdatingBackgroundTask() {
// public void execute() {
// updateListener(res.getString(PRIMARY_INITIALIZING));
// synchronized (BBSSHApp.inst().getInitializationMutex()) {
// // no action - just want to block ehre until the init task is complete.
// Note that
// // we couldn't block in the main thread above, as that would prevent UI
// refreshes from occurring -
// // we wouldn't show our "please wait"...
// }
// }
// }, false);
// wait.launch();
// Logger.info("Initialization complete - continuing with primaryscreen display.");
//
// }
protected ConnectionProperties getPropertiesForCurrentSelection() {
return getPropertiesForNode(sessions.getSelectedIndex());
}
protected ConnectionProperties getPropertiesForNode(int node) {
if (node == -1)
return null;
Vector v = ConnectionManager.getInstance().getConnections();
if (v.size() > node)
return (ConnectionProperties) v.elementAt(node);
return null;
}
public void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
int node = sessions.getSelectedIndex();
ConnectionProperties prop = getPropertiesForNode(node);
RemoteSessionInstance inst = getSelectedRemoteSessionInstance();
MenuItem def;
boolean connectedInstance = inst != null && inst.session.isConnectionActive();
boolean context = (instance == Menu.INSTANCE_CONTEXT);
// Anything that has an instance associated with it can eitehr
// resume the session, or terminate it (disconnect and close)
if (inst == null) {
// Current or formerly active session
if (prop == null) {
// no selection at all...
def = connectionCreateNew;
} else {
def = sessionConnect;
menu.add(sessionConnect);
}
} else {
def = sessionResume;
menu.add(sessionResume);
if (connectedInstance) {
menu.add(sessionDisconnect);
if (!context) {
menu.add(sessionTerminate);
}
} else {
menu.add(sessionReconnect);
menu.add(sessionTerminate);
}
}
if (!connectedInstance) {
menu.add(connectionDelete);
}
menu.add(connectionEdit);
if (context) {
if (inst == null) {
menu.add(connectionCreateNew);
}
} else {
menu.add(connectionCreateNew);
if (prop != null) {
menu.add(connectionDuplicate);
}
// These are always available.
menu.add(keyManager);
menu.add(keyBindMenu);
menu.add(macrosMenu);
menu.add(settingsMenu);
menu.add(HelpManager.getHelpMenu());
menu.add(sendFeedback);
menu.add(aboutMenu);
}
menu.setDefault(def);
}
private void backdoorLogLevel(final int level, final String desc) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Logger.setLogLevel(level);
Status.show("Logging set to " + desc);
}
});
}
private void backdoorToggleFileLogging(final boolean enable) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
if (enable) {
if (Logger.isFileLoggingEnabled()) {
Status.show("Logging is already enabled. Logs being written to: " + Logger.getFileName());
} else {
try {
if (BBSSHApp.inst().requestPermission(ApplicationPermissions.PERMISSION_FILE_API,
BBSSHResource.MSG_PERMISSIONS_MISSING_FILE_ACCESS_LOGGING)) {
Logger.enableFileLogging();
Status.show("Logging enabled enabled. Logs being written to: " + Logger.getFileName());
}
} catch (Throwable t) {
Status.show("Unable to enable logging to file due to error " + t.getMessage().toString()
+ " : " + t.getMessage());
}
}
} else {
if (Logger.isFileLoggingEnabled()) {
Logger.disableFileLogging();
Status.show("Logging output file turned off");
} else {
Status.show("Logging to file was not enabled to begin with.");
}
}
}
});
}
private void backdoorDoStartupDialogs() {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Settings s = SettingsManager.getSettings();
s.setRememberOption(Settings.REMEMBER_LICENSE_AGREEMENT_COMPLETE, false);
s.setRememberOption(Settings.REMEMBER_CHECKED_UPDATE_OK, false);
s.setRememberOption(Settings.REMEMBER_CHECKED_SEND_USAGE_STATS_OK, false);
showStartupDialogs();
}
});
}
protected boolean openProductionBackdoor(int backdoorCode) {
switch (backdoorCode) {
case ('L' << 24) | ('Y' << 16) | ('O' << 8) | 'T': // LYOT
Status.show("Layout data written to log file");
PlatformServicesProvider.getInstance().determineLayout();
return true;
case ('L' << 24) | ('G' << 16) | ('M' << 8) | 'X': // LGMX
backdoorLogLevel(Logger.LOG_LEVEL_DEBUG, "debug/full.");
return true;
case ('L' << 24) | ('G' << 16) | ('I' << 8) | 'N': // LGIN
backdoorLogLevel(Logger.LOG_LEVEL_INFO, "info/trace.");
return true;
case ('L' << 24) | ('G' << 16) | ('W' << 8) | 'N': // LGWN
backdoorLogLevel(Logger.LOG_LEVEL_WARN, "warn (default).");
return true;
case ('L' << 24) | ('G' << 16) | ('T' << 8) | 'M': // LGTM // toggle terminal logging
backdoorToggleTerminalLogging();
return true;
case ('L' << 24) | ('G' << 16) | ('F' << 8) | 'S': // LGFS // log file start
backdoorToggleFileLogging(true);
return true;
case ('L' << 24) | ('G' << 16) | ('F' << 8) | 'X': // LGFX // log file end
backdoorToggleFileLogging(false);
return true;
case ('P' << 24) | ('R' << 16) | ('M' << 8) | 'S': // PRMS
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new PermissionsHelperScreen(false));
}
});
return true;
case ('S' << 24) | ('T' << 16) | ('R' << 8) | 'T': // STRT
backdoorDoStartupDialogs();
return true;
case ('B' << 24) | ('N' << 16) | ('D' << 8) | 'B': // BNDB
new Thread(new Runnable() {
public void run() {
KeyBindingManager.getInstance().setDebugBindings();
}
}).start();
return true;
case ('R' << 24) | ('C' << 16) | ('V' << 8) | 'R': // RCVR
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushModalScreen(
new RecoveryScreen(BBSSHResource.RECOVERY_INSTRUCTION));
forceClose = true;
close();
}
});
return true; // handled
}
return super.openProductionBackdoor(backdoorCode);
}
private void backdoorToggleTerminalLogging() {
ConnectionProperties prop = getPropertiesForCurrentSelection();
if (prop == null)
return;
Dialog.ask(Dialog.D_OK, res.getString(prop.isCaptureEnabled() ? BBSSHResource.PRIMARY_TERMINAL_LOGGING_DISABLED
: BBSSHResource.PRIMARY_TERMINAL_LOGGING_ENABLED));
prop.setCaptureEnabled(!prop.isCaptureEnabled());
}
protected RemoteSessionInstance getSelectedRemoteSessionInstance() {
return SessionManager.getInstance().getFirstSession(getPropertiesForCurrentSelection());
}
protected boolean keyChar(char c, int status, int time) {
switch (c) {
case Keypad.KEY_ENTER:
handleResumeOrConnectSession();
return true;
case 'e':
case 'E':
showSessionDetailScreen(false);
return true;
case 'c':
case 'C':
showSessionDetailScreen(true);
return true;
case Keypad.KEY_BACKSPACE:
case 'd':
case 'D':
handleDeleteCurrentSession();
return true;
}
return super.keyChar(c, status, time);
}
private void startCloseTasks() {
PleaseWaitTaskMonitorScreen m = new PleaseWaitTaskMonitorScreen(new UpdatingBackgroundTask() {
public void execute() {
updateListener("Shutting down...");
BBSSHApp.inst().shutdownTasks();
}
});
// we'll go to the background and begin our shutdown. It shouldn't take long, but this way we're immediately
// responsive while we do any required cleanup tasks.
UiApplication.getUiApplication().requestBackground();
m.launch();
super.close();
}
public void close() {
if (forceClose) {
// A sloppy close, requested due to corrupt state.
super.close();
System.exit(-1);
return;
}
SessionManager mgr = SessionManager.getInstance();
if (mgr.doesActiveSessionExist()) {
Settings s = SettingsManager.getSettings();
// If this was explicitly set, then just do what the user siad.
if (s.getRememberOption(Settings.REMEMBER_OPT_BACKGROUND_ON_CLOSE)) {
if (s.isBackgroundOnCloseEnabled()) {
UiApplication.getUiApplication().requestBackground();
} else {
startCloseTasks();
}
return;
}
// Prompt if they haven't set it.
int result =
MemoryDialog.ask(BBSSHResource.MSG_CONFIRM_EXIT_CONN_OPEN, new int[] {
BBSSHResource.MSG_CONFIRM_EXIT_ANS_BACKGROUND, BBSSHResource.MSG_CONFIRM_EXIT_ANS_EXIT,
BBSSHResource.MSG_CONFIRM_EXIT_ANS_NEVERMIND
}, 0);
if (result == 2) { // nevermind
return;
}
boolean background = (result == 0);
// Remember?
if (MemoryDialog.getRememberSelection()) {
s.setRememberOption(Settings.REMEMBER_OPT_BACKGROUND_ON_CLOSE, true);
s.setBackgroundOnClose(background);
}
if (background) {
UiApplication.getUiApplication().requestBackground();
return;
}
}
startCloseTasks();
}
/**
* Displays session detail screen for the selected item, first copying the properties before modification. This is
* so that we don't incorrectly persist updates that the user does not want to retain. validates that if a new
* session is not being created, that a valid session is selected. Once the detail form completes, this will save
* the updates.
*
* @param newSession
* indicates whether the user is creating a new sessions.
*/
private void showSessionDetailScreen(boolean newSession) {
ConnectionProperties prop;
if (newSession) {
prop = new ConnectionProperties(SettingsManager.getSettings().getDefaultConnectionProperties(), true);
} else {
prop = getPropertiesForCurrentSelection();
if (prop == null) {
return;
}
}
editConnectionProperties(prop);
}
public void editConnectionProperties(final ConnectionProperties prop) {
Application.getApplication().invokeLater(new Runnable() {
public void run() {
curDetailScreen = new ConnectionInstancePropertiesScreen(prop);
UiApplication.getUiApplication().pushScreen(curDetailScreen);
}
});
}
/**
* Override of onExposed, we are using this to perform appropriate behavior when the user returns from
* defining/editing a session, or to switch session screens.
*/
protected void onExposed() {
if (sessions == null) {
return;
}
SessionManager.getInstance().notifySessionListExposed();
//
// This can get exposed when returning from a live session
// so we will need to invalidate our list -- this will cause
// use to properly reflect active state of connections and
// notifications.
invalidate();
// If we weren't in the process of editing a connection,
// we don't have any further action to take here.
if (curDetailScreen == null || !curDetailScreen.isSaved()) {
return;
}
// Finally, if the changes were saved, update the array with our
// current copy.
Logger.info("PrimaryScreen.onExposed: returning from saved session edit, updating.");
ConnectionProperties prop = curDetailScreen.getEditedProperties();
addAndRefresh(prop);
curDetailScreen = null;
if (SessionManager.getInstance().getFirstConnectedSession(prop) != null) {
Dialog.inform(res.getString(BBSSHResource.PRIMARY_SOME_CHANGES_NEED_RECONNECT));
}
}
protected void addAndRefresh(ConnectionProperties prop) {
if (prop == null)
return;
Logger.info("PrimaryScreen.addAndRefresh - start");
Vector v = ConnectionManager.getInstance().getConnections();
ConnectionProperties orig =
ConnectionManager.getInstance().getConnectionPropertiesById(Integer.toString(prop.getUID()));
if (prop.isNew() || orig == null) {
Logger.info("PrimaryScreen.addAndRefresh - conn is new, clearing new flag.");
prop.setNew(false);
v.addElement(prop);
} else {
Logger.info("PrimaryScreen.addAndRefresh - conn is existing, replacing it: " + orig.getName() + " -> "
+ prop.getName());
// @todo better search for original
// Inefficient search, but it'll work for now - most folks aren't
// looking at hundreds of defined connectionss.
int idx = v.lastIndexOf(orig);
if (idx == -1) {
Logger.error("PS.ar - could not find original connection ");
return;
}
Logger.info("PrimaryScreen.addAndRefresh - replacing at index: " + idx);
v.setElementAt(prop, idx);
}
Tools.sortVector(v);
populateConnectionList();
saveConnections();
}
private void saveConnections() {
// @todo - race possibility here, need to be much cleaner about this.
new Thread() {
public void run() {
ConnectionManager.getInstance().commitData();
};
}.start();
}
public void startOrResumeSession(ConnectionProperties prop) {
SessionManager mgr = SessionManager.getInstance();
RemoteSessionInstance inst = SessionManager.getInstance().getFirstSession(prop);
if (inst == null) {
handleConnectSession();
} else {
mgr.setActiveSession(inst);
}
}
private void handleResumeOrConnectSession() {
RemoteSessionInstance inst = getSelectedRemoteSessionInstance();
if (inst == null) {
handleConnectSession();
} else {
SessionManager.getInstance().setActiveSession(inst);
}
}
private void handleReconnectSession() {
RemoteSessionInstance inst = getSelectedRemoteSessionInstance();
SessionManager.getInstance().reconnectSession(inst);
}
/**
* opens and initiates connection of the selected session after first verifying permissions.
*/
private void handleConnectSession() {
// int node = sessions.getSelectedIndex();
ConnectionProperties prop = getPropertiesForCurrentSelection();
if (prop == null)
return;
if (prop.getUseWifiIfAvailable()) {
// No big deal if we can't get this - at least we have TCP
if (!BBSSHApp.inst().requestPermission(
ConnectionHelper.getPermissionForConnType(ApplicationPermissions.PERMISSION_WIFI),
BBSSHResource.MSG_NET_PERMISSIONS_MISSING_WIFI)) {
Logger.error("Expected failure - permission denied for wifi attempt.");
}
}
if (!BBSSHApp.inst().requestPermission(ConnectionHelper.getPermissionForConnType(prop.getConnectionType()),
BBSSHResource.MSG_NET_PERMISSIONS_MISSING_ADD_NOW)) {
Logger.error("Cannot complete connection due to permissions denied for selected connection type.");
return;
}
if (SettingsManager.getSettings().isHomeScreenNotificationIconEnabled()) {
if (!BBSSHApp.inst().requestPermission(ApplicationPermissions.PERMISSION_MEDIA,
BBSSHResource.MSG_PERMISSIONS_MISSING_MEDIA)) {
Logger.error("Disabling home screen notifications due to permission denied.");
SettingsManager.getSettings().setHomeScreenNotificationIconEnabled(false);
SettingsManager.getInstance().commitData();
}
}
SessionManager.getInstance().connectSession(prop);
// Refresh with latest info. For now we're being lazy and just
// repopulating the whole thing.
populateConnectionList();
// // Okay - if a connection exists...
// if (sessions.getCookie(node) instanceof ConnectionProperties) {
// // Let session manager figure out what's going on for this definition
// ...
// SessionManager.getInstance().initiateOrResumeSession(
// (ConnectionProperties) sessions.getCookie(node));
// } else {
// SessionManager.getInstance().setActiveSession(nodeConnectionMap.get(node));
// }
}
/**
* Check for updates.
*/
private void performBackgroundUpdateCheck() {
Settings s = SettingsManager.getSettings();
// Development mode not allowed to bypass auto update checks.
if (Version.isReleaseMode() && !s.isAutoCheckUpdateEnabled() && !s.isAnonymousUsageStatsEnabled()) {
return;
}
// Do our check in the background thread so as not to block the main
// thread at all.
new Thread("Updates") {
public void run() {
Version.checkAndPromptForUpdates(false);
}
}.start();
}
protected void handleDuplicateSession() {
ConnectionProperties prop = getPropertiesForCurrentSelection();
if (prop == null)
return;
ConnectionProperties newProp = new ConnectionProperties(prop);
newProp.setName(newProp.getName() + res.getString(BBSSHResource.IND_COPY));
addAndRefresh(newProp);
}
private void showStartupDialogs() {
boolean saveNeeded = false;
Settings s = SettingsManager.getSettings();
if (!s.areInitialOptionsSet()) {
UiApplication.getUiApplication().pushModalScreen(new StartupPopup());
if (!s.getRememberOption(Settings.REMEMBER_LICENSE_AGREEMENT_COMPLETE)) {
Logger.error("License agreement not completed, closing.");
System.exit(0);
return;
}
saveNeeded = true;
}
if (!Version.doesAppVersionMatchOSVersion()) {
if (Dialog.ask(Dialog.D_YES_NO, res.getString(BBSSHResource.MSG_WRONG_VERSION), 0) == Dialog.YES) {
Version.goToDownloadSite();
System.exit(0);
Logger.error("Not using latest OS version, user chose download. Terminating.");
} else {
Logger.error("Not using latest OS version, user ignores.");
}
}
if (!s.getRememberOption(Settings.REMEMBER_DO_NOT_SHOW_DATA_WARN)) {
MemoryDialog.ask(BBSSHResource.MSG_DATA_USAGE_WARN, new int[] {
BBSSHResource.GENERAL_LBL_OK
}, 0);
if (MemoryDialog.getRememberSelection()) {
s.setRememberOption(Settings.REMEMBER_DO_NOT_SHOW_DATA_WARN, true);
saveNeeded = true;
}
}
if (saveNeeded)
SettingsManager.getInstance().commitData();
// @todo reinstate this once it's human-usable. It's a mess right now
// ...
// if (!s.getRememberOption(Settings.REMEMBER_PERM_SHOWN)) {
// UiApplication.getUiApplication().pushScreen(new
// PermissionsHelperScreen(false));
//
// }
}
public void refreshConnections() {
// invalidate();
// doens't exist for some reason... very odd since it inherits from
// Field...
sessions.invalidate();
}
/**
* If the app version supports homescreen shortcuts, override this to remove the specifeid shortcut
*/
protected void removeShortcut(ConnectionProperties prop) {
// homescreen shortcuts not supported until 6.0
}
private boolean handleDeleteCurrentSession() {
ConnectionProperties prop = getPropertiesForCurrentSelection();
ConnectionManager cfg = ConnectionManager.getInstance();
if (prop == null)
return false;
if (SessionManager.getInstance().getFirstConnectedSession(prop) != null) {
Status.show(res.getString(BBSSHResource.MSG_NOT_ALLOWED_CONNECTED));
return false;
}
// note that we do allow existing sessions that are not connected.
if (Dialog.ask(Dialog.D_DELETE, res.getString(BBSSHResource.MSG_CONFIRM_DEL_CONNECTION), 0) == Dialog.DELETE) {
// @todo - should this be in the background?
SessionManager mgr = SessionManager.getInstance();
Vector sessions = mgr.getSessions(prop);
if (sessions != null) {
for (int x = 0; x < sessions.size(); x++) {
mgr.terminateSession((RemoteSessionInstance) sessions.elementAt(x));
}
}
removeShortcut(prop);
Vector v = cfg.getConnections();
v.removeElement(prop);
Tools.sortVector(v);
saveConnections();
populateConnectionList();
return true;
}
return false;
}
}