/**
* Copyright (c) 2010 Perforce Software. All rights reserved.
*/
package com.perforce.p4scout;
import static com.perforce.p4scout.Constants.CALLER;
import static com.perforce.p4scout.Constants.CHANGENUM;
import static com.perforce.p4scout.Constants.ERROR;
import static com.perforce.p4scout.Constants.ID;
import static com.perforce.p4scout.Constants.JOBID;
import static com.perforce.p4scout.Constants.PASSWORDINVALID;
import static com.perforce.p4scout.Constants.PASSWORDNOTSET;
import static com.perforce.p4scout.Constants.SESSIONLOGGEDOUT;
import java.util.List;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import com.perforce.p4java.core.IChangelist;
import com.perforce.p4java.core.IJob;
import com.perforce.p4java.core.file.IFileSpec;
import com.perforce.p4scout.ChangeDetailAdapter.ItemType;
/**
* This class displays a changelist from a Perforce Server. Extras:
*
* <ul><li>ID The ServerId from the P4SERVERS table (required)
* <li>int CHANGENUM The changelist number (required)</ul>
*/
public class ChangeDetail extends Activity {
protected ProgressDialog loading;
protected Context context;
protected String serverId;
protected PerforceSession serverCaller;
protected ChangeDetailAdapter changeAdapter;
protected IChangelist changeData;
protected List<IFileSpec> fileCache;
protected List<IJob> jobCache;
protected int fileError = 0;
protected int filesToGet = 25;
protected boolean jobsError = false;
protected boolean working = true;
private Thread[] runner;
/** The Handler for displaying errors */
private Handler errorHandle;
/** The Handler for updating the changelist details in the View */
private Handler detailUpdateHandle = new Handler();
/**
* The Runnable for updating the changelist details in the View.
* This requires changeData, fileCache and jobCache to be populated.
*
* @see com.perforce.p4scout.ChangeDetail#getChange(int, String, String)
*/
private Runnable detailUpdateUpdater = new Runnable() {
public void run() {
if (changeData != null) {
changeAdapter.addChangeDetails(changeData);
changeAdapter.notifyDataSetChanged();
loading.dismiss();
}
if (fileCache != null && fileError == 0) {
changeAdapter.addFileSpecs(fileCache);
changeAdapter.notifyDataSetChanged();
} else if (fileError == 1) {
changeAdapter.tooManyFiles();
changeAdapter.notifyDataSetChanged();
} else if (fileError == 2) {
changeAdapter.serverTooOld();
changeAdapter.notifyDataSetChanged();
}
if (jobCache != null && jobsError == false) {
changeAdapter.addJobs(jobCache);
changeAdapter.notifyDataSetChanged();
// This is always the last set of results
setProgressBarIndeterminateVisibility(false);
} else if (jobsError == true) {
changeAdapter.tooManyJobs();
changeAdapter.notifyDataSetChanged();
// Unless this is the last set of results
setProgressBarIndeterminateVisibility(false);
}
}
};
/**
* Gets the changelist and calls the update handler.
*
* @param changeId the changelist number (required)
*
* @see com.perforce.p4scout.ChangeDetail#detailUpdateUpdater
*/
private void getChange(final int changeId) {
class Worker extends Thread {
@Override
public void run() {
try {
serverCaller.connect(true);
changeData = serverCaller.getChangelist(changeId);
if (Thread.interrupted()) {
return;
}
detailUpdateHandle.post(detailUpdateUpdater);
try {
fileCache = serverCaller.changeExceedsLimit(changeId, filesToGet);
if (Thread.interrupted()) {
return;
}
if (fileCache == null) {
fileError = 1;
}
} catch (Throwable p4e) {
fileError = 2;
fileCache = null;
}
detailUpdateHandle.post(detailUpdateUpdater);
try {
jobCache = changeData.getJobs();
if (Thread.interrupted()) {
return;
}
if (jobCache.size() > 100) {
jobsError = true;
fileCache = null;
}
} catch (Throwable p4e) {
jobsError = true;
fileCache = null;
}
detailUpdateHandle.post(detailUpdateUpdater);
serverCaller.disconnect();
} catch (final Exception e) {
if (Thread.interrupted()) {
return;
}
errorHandle.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), e.getMessage().trim(),
Toast.LENGTH_LONG).show();
if (e.getMessage().trim().contains(PASSWORDINVALID) ||
e.getMessage().trim().contains(SESSIONLOGGEDOUT) ||
e.getMessage().trim().contains(PASSWORDNOTSET)) {
Intent loginIntent = new Intent(context, LoginDialog.class);
loginIntent.putExtra(ID, serverId);
loginIntent.putExtra(ERROR, e.getMessage());
loginIntent.putExtra(CALLER, getLocalClassName());
startActivity(loginIntent);
}
}
});
e.printStackTrace();
finish();
}
}
}
runner[0] = new Worker();
runner[0].start();
}
/**
* This is the initialisation method for the changelist detail view.<br/>
* This displays the view and kicks off the Perforce commands in a new thread.
*
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
errorHandle = new Handler(Looper.getMainLooper());
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.changedetail);
setProgressBarIndeterminateVisibility(true);
loading = new ProgressDialog(this);
runner = new Thread[1];
Intent i = getIntent();
Bundle extras = i.getExtras();
serverId = (String) extras.get(ID);
int changeId = extras.getInt(CHANGENUM);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
filesToGet = Integer.parseInt(sp.getString("prefGetChangeFiles", "25"));
changeAdapter = new ChangeDetailAdapter(context);
ListView changeDetailsList = (ListView) findViewById(R.id.lvChangeDetails);
changeDetailsList.setAdapter(changeAdapter);
changeDetailsList.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (changeAdapter.getItem(position) == ItemType.JOB &&
changeAdapter.getJob(position) != null) {
Intent i = new Intent(context, JobDetail.class);
i.putExtra(JOBID, changeAdapter.getJob(position).getId());
i.putExtra(ID, serverId);
startActivity(i);
}
}
});
serverCaller = new PerforceSession(this, serverId);
setTitle(getString(R.string.strChangelistSpc) + " " + Integer.toString(changeId) +
" - " + serverCaller.getServerName());
if (changeId > 0) {
loading.setIndeterminate(true);
loading.setMessage(getString(R.string.tvLoading));
loading.show();
getChange(changeId);
} else {
// No changelists lower than 1 can possibly exist.
loading.dismiss();
Toast tt = Toast.makeText(this, getString(R.string.ttInvalidChange), Toast.LENGTH_LONG);
tt.show();
this.finish();
}
}
/**
* This kills all background threads when we exit. There is no need for them to consume
* resources when we are doing something else.
*/
@Override
protected void onPause() {
super.onPause();
if (runner == null) {
return;
}
for (int i=0; i<runner.length; i++) {
if (runner[i] != null) {
runner[i].interrupt();
}
}
}
/**
* This prevents the activity from being restarted when the orientation changes
*/
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
}
# |
Change |
User |
Description |
Committed |
|
#1
|
8980 |
Matt Attaway |
Add source code for both the Android and iOS versions of P4Scout. |
|
|