aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml8
-rw-r--r--res/layout/init.xml20
-rw-r--r--res/layout/mapfile_item.xml33
-rw-r--r--res/values/strings.xml7
-rw-r--r--src/cgeo/geocaching/cgFileList.java260
-rw-r--r--src/cgeo/geocaching/cgMapfileListAdapter.java90
-rw-r--r--src/cgeo/geocaching/cgSelectMapfile.java55
-rw-r--r--src/cgeo/geocaching/cgeoinit.java40
8 files changed, 505 insertions, 8 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 928a0b8..9b92d7f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -280,5 +280,13 @@
<action android:name="cgeo.geocaching.CGEOGPXES"/>
</intent-filter>
</activity>
+ <activity
+ android:name=".cgSelectMapfile"
+ android:label="@string/app_name"
+ android:configChanges="keyboardHidden|orientation" >
+ <intent-filter>
+ <action android:name="cgeo.geocaching.CGEOSELMAP"/>
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/res/layout/init.xml b/res/layout/init.xml
index 3f4d893..33354f0 100644
--- a/res/layout/init.xml
+++ b/res/layout/init.xml
@@ -494,11 +494,21 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="@string/init_mapsource_select" />
- <EditText style="@style/edittext"
- android:id="@+id/mapfile"
- android:singleLine="true"
- android:lines="1"
- android:scrollHorizontally="true" />
+ <LinearLayout
+ android:id="@+id/init_mapfilegroup"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+ <Button style="@style/button"
+ android:id="@+id/select_mapfile"
+ android:text="@string/init_select_mapfile"
+ android:layout_width="wrap_content" />
+ <EditText style="@style/edittext"
+ android:id="@+id/mapfile"
+ android:singleLine="true"
+ android:lines="1"
+ android:scrollHorizontally="true" />
+ </LinearLayout>
<!-- ** -->
<RelativeLayout style="@style/separator_horizontal_layout" >
<View style="@style/separator_horizontal" />
diff --git a/res/layout/mapfile_item.xml b/res/layout/mapfile_item.xml
new file mode 100644
index 0000000..a024b81
--- /dev/null
+++ b/res/layout/mapfile_item.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/mapfile_item"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_margin="3dip"
+ android:paddingLeft="5dip"
+ android:paddingRight="5dip"
+ android:paddingBottom="7dip"
+ android:paddingTop="7dip"
+ android:orientation="vertical"
+ android:background="?background_color" >
+ <TextView android:id="@+id/mapfilepath"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:scrollHorizontally="true"
+ android:textSize="12dip"
+ android:gravity="right"
+ android:lines="1"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textColor="?text_color_grey" />
+ <TextView android:id="@+id/mapfilename"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:scrollHorizontally="true"
+ android:textSize="22dip"
+ android:gravity="left"
+ android:lines="1"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textColor="?text_color" />
+</LinearLayout> \ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6c9ab8f..2266c6d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -402,6 +402,7 @@
<string name="init_mapsources">Map Sources</string> <!-- since: 2.26 RC3 -->
<string name="init_mapsources_description">Here you can select the source for your maps. As an alternative to Google maps various OpenStreetMap styles are available and even off line map files (see http://code.google.com/p/mapsforge/ for details).</string> <!-- since: 2.26 RC3 -->
<string name="init_mapsource_select">Select map source</string>
+ <string name="init_select_mapfile">...</string>
<!-- map sources -->
<string-array name="map_sources">
@@ -511,6 +512,12 @@
<string name="cache_spoiler_images_loading">Loading spoiler images...</string>
<string name="cache_log_types">Log types</string> <!-- since: 2.10 RC2 -->
<string name="cache_coordinates_no">This cache has no coordinates.</string> <!-- since: 2.26 RC2 -->
+
+ <!-- file list base -->
+ <string name="file_searching_in">Searching for files\nin</string>
+ <string name="file_list_no_files">Sorry, c:geo found no appropriate files.</string>
+ <string name="file_searching">Searching for matching files</string>
+ <string name="file_title_searching">Searching</string>
<!-- gpx -->
<string name="gpx_import_searching_in">Searching for .gpx files\nin</string>
diff --git a/src/cgeo/geocaching/cgFileList.java b/src/cgeo/geocaching/cgFileList.java
new file mode 100644
index 0000000..2767cfe
--- /dev/null
+++ b/src/cgeo/geocaching/cgFileList.java
@@ -0,0 +1,260 @@
+package cgeo.geocaching;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.app.ListActivity;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.widget.ArrayAdapter;
+
+public abstract class cgFileList<T extends ArrayAdapter<File>> extends ListActivity {
+
+ private ArrayList<File> files = new ArrayList<File>();
+ private cgeoapplication app = null;
+ private cgSettings settings = null;
+ private cgBase base = null;
+ private cgWarning warning = null;
+ private Activity activity = null;
+ private T adapter = null;
+ private ProgressDialog waitDialog = null;
+ private Resources res = null;
+ private loadFiles searchingThread = null;
+ private boolean endSearching = false;
+ private int listId = 1;
+ final private Handler changeWaitDialogHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.obj != null && waitDialog != null) {
+ waitDialog.setMessage(res.getString(R.string.file_searching_in) + " " + (String) msg.obj);
+ }
+ }
+ };
+ final private Handler loadFilesHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ if (files == null || files.isEmpty()) {
+ if (waitDialog != null) {
+ waitDialog.dismiss();
+ }
+
+ warning.showToast(res.getString(R.string.file_list_no_files));
+
+ finish();
+ return;
+ } else {
+ if (adapter != null) {
+ adapter.notifyDataSetChanged();
+ }
+ }
+
+ if (waitDialog != null) {
+ waitDialog.dismiss();
+ }
+ } catch (Exception e) {
+ if (waitDialog != null) {
+ waitDialog.dismiss();
+ }
+ Log.e(cgSettings.tag, "cgFileList.loadFilesHandler: " + e.toString());
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // init
+ activity = this;
+ res = this.getResources();
+ app = (cgeoapplication) this.getApplication();
+ settings = new cgSettings(this, getSharedPreferences(cgSettings.preferences, 0));
+ base = new cgBase(app, settings, getSharedPreferences(cgSettings.preferences, 0));
+ warning = new cgWarning(this);
+
+ // set layout
+ if (settings.skin == 1) {
+ setTheme(R.style.light);
+ } else {
+ setTheme(R.style.dark);
+ }
+ setContentView(R.layout.gpx);
+ base.setTitle(activity, res.getString(R.string.gpx_import_title));
+
+ // google analytics
+ base.sendAnal(activity, "/file-import");
+
+ Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ listId = extras.getInt("list");
+ }
+ if (listId <= 0) {
+ listId = 1;
+ }
+
+ setAdapter();
+
+ waitDialog = ProgressDialog.show(
+ this,
+ res.getString(R.string.file_title_searching),
+ res.getString(R.string.file_searching),
+ true,
+ true,
+ new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface arg0) {
+ if (searchingThread != null && searchingThread.isAlive()) {
+ searchingThread.notifyEnd();
+ }
+ if (files.isEmpty() == true) {
+ finish();
+ }
+ }
+ }
+ );
+
+ endSearching = false;
+ searchingThread = new loadFiles();
+ searchingThread.start();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ settings.load();
+ }
+
+ final protected cgSettings getSettings() {
+ return settings;
+ }
+
+ protected abstract T getAdapter(ArrayList<File> files);
+
+ private void setAdapter() {
+ if (adapter == null) {
+ adapter = getAdapter(files);
+ setListAdapter(adapter);
+ }
+ }
+
+ /**
+ * Gets the base folder for file searches
+ * @return The folder to start the recursive search in
+ */
+ protected abstract String[] getBaseFolders();
+
+ private class loadFiles extends Thread {
+ public void notifyEnd() {
+ endSearching = true;
+ }
+
+ @Override
+ public void run() {
+ ArrayList<File> list = new ArrayList<File>();
+
+ try {
+ if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) == true) {
+ boolean loaded = false;
+ for(String baseFolder : getBaseFolders())
+ {
+ final File dir = new File(baseFolder);
+
+ if (dir.exists() && dir.isDirectory()) {
+ listDir(list, dir);
+ if (list.size() > 0) {
+ loaded = true;
+ break;
+ }
+ }
+ }
+ if (!loaded) {
+ listDir(list, Environment.getExternalStorageDirectory());
+ }
+ } else {
+ Log.w(cgSettings.tag, "No external media mounted.");
+ }
+ } catch (Exception e) {
+ Log.e(cgSettings.tag, "cgFileList.loadFiles.run: " + e.toString());
+ }
+
+ final Message msg = new Message();
+ msg.obj = "loaded directories";
+ changeWaitDialogHandler.sendMessage(msg);
+
+ files.addAll(list);
+ list.clear();
+
+ loadFilesHandler.sendMessage(new Message());
+ }
+ }
+
+ /**
+ * Get the file extension to search for
+ * @return The file extension
+ */
+ protected abstract String getFileExtension();
+
+ private void listDir(ArrayList<File> list, File directory) {
+ if (directory == null || directory.isDirectory() == false || directory.canRead() == false) {
+ return;
+ }
+
+ final File[] listPre = directory.listFiles();
+ String fileExt = getFileExtension();
+
+ if (listPre != null && listPre.length > 0) {
+ final int listCnt = listPre.length;
+
+ for (int i = 0; i < listCnt; i++) {
+ if (endSearching == true) {
+ return;
+ }
+
+ if (listPre[i].canRead() == true && listPre[i].isFile() == true) {
+ final String[] nameParts = listPre[i].getName().split("\\.");
+ if (nameParts.length > 1) {
+ final String extension = nameParts[(nameParts.length - 1)].toLowerCase();
+
+ if (extension.equals(fileExt) == false) {
+ continue;
+ }
+ } else {
+ continue; // file has no extension
+ }
+
+ list.add(listPre[i]); // add file to list
+ } else if (listPre[i].canRead() == true && listPre[i].isDirectory() == true) {
+ final Message msg = new Message();
+ String name = listPre[i].getName();
+ if (name.substring(0, 1).equals(".") == true) {
+ continue; // skip hidden directories
+ }
+ if (name.length() > 16) {
+ name = name.substring(0, 14) + "...";
+ }
+ msg.obj = name;
+ changeWaitDialogHandler.sendMessage(msg);
+
+ listDir(list, listPre[i]); // go deeper
+ }
+ }
+ }
+
+ return;
+ }
+
+ public void goHome(View view) {
+ base.goHome(activity);
+ }
+}
diff --git a/src/cgeo/geocaching/cgMapfileListAdapter.java b/src/cgeo/geocaching/cgMapfileListAdapter.java
new file mode 100644
index 0000000..ba12280
--- /dev/null
+++ b/src/cgeo/geocaching/cgMapfileListAdapter.java
@@ -0,0 +1,90 @@
+package cgeo.geocaching;
+
+import java.io.File;
+import java.util.List;
+
+import android.app.Activity;
+import android.graphics.Typeface;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+public class cgMapfileListAdapter extends ArrayAdapter<File> {
+
+ private cgSelectMapfile parentView;
+ private LayoutInflater inflater;
+ private MapfileView holder;
+
+ public cgMapfileListAdapter(cgSelectMapfile parentIn, List<File> listIn) {
+ super(parentIn, 0, listIn);
+
+ parentView = parentIn;
+ }
+
+ @Override
+ public View getView(int position, View rowView, ViewGroup parent) {
+ if (inflater == null) inflater = ((Activity)getContext()).getLayoutInflater();
+
+ if (position > getCount()) {
+ Log.w(cgSettings.tag, "cgGPXListAdapter.getView: Attempt to access missing item #" + position);
+ return null;
+ }
+
+ File file = getItem(position);
+
+ if (rowView == null) {
+ rowView = (View)inflater.inflate(R.layout.mapfile_item, null);
+
+ holder = new MapfileView();
+ holder.filepath = (TextView)rowView.findViewById(R.id.mapfilepath);
+ holder.filename = (TextView)rowView.findViewById(R.id.mapfilename);
+
+ rowView.setTag(holder);
+ } else {
+ holder = (MapfileView)rowView.getTag();
+ }
+
+ File current = new File(parentView.getCurrentMapfile());
+
+ if (file.equals(current)) {
+ holder.filename.setTypeface(holder.filename.getTypeface(), Typeface.BOLD);
+ } else {
+ holder.filename.setTypeface(holder.filename.getTypeface(), Typeface.NORMAL);
+ }
+
+ final touchListener touchLst = new touchListener(file);
+ rowView.setOnClickListener(touchLst);
+
+ holder.filepath.setText(file.getParent());
+ holder.filename.setText(file.getName());
+
+ return rowView;
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ super.notifyDataSetChanged();
+ }
+
+ private class touchListener implements View.OnClickListener {
+ private File file = null;
+
+ public touchListener(File fileIn) {
+ file = fileIn;
+ }
+
+ // tap on item
+ public void onClick(View view) {
+ parentView.setMapfile(file.toString());
+ parentView.close();
+ }
+ }
+
+ private class MapfileView {
+ public TextView filepath;
+ public TextView filename;
+ }
+}
diff --git a/src/cgeo/geocaching/cgSelectMapfile.java b/src/cgeo/geocaching/cgSelectMapfile.java
new file mode 100644
index 0000000..b64148f
--- /dev/null
+++ b/src/cgeo/geocaching/cgSelectMapfile.java
@@ -0,0 +1,55 @@
+package cgeo.geocaching;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Environment;
+
+public class cgSelectMapfile extends cgFileList<cgMapfileListAdapter> {
+
+ String mapFile;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mapFile = getSettings().getMapFile();
+ }
+
+ public void close() {
+
+ Intent intent = new Intent();
+ intent.putExtra("mapfile", mapFile);
+
+ setResult(RESULT_OK, intent);
+
+ finish();
+ }
+
+ @Override
+ protected cgMapfileListAdapter getAdapter(ArrayList<File> files) {
+ return new cgMapfileListAdapter(this, files);
+ }
+
+ @Override
+ protected String[] getBaseFolders() {
+ String base = Environment.getExternalStorageDirectory().toString();
+ return new String[]{base + "/mfmaps", base + "/Locus/mapsVector"};
+ }
+
+ @Override
+ protected String getFileExtension() {
+ return "map";
+ }
+
+ public String getCurrentMapfile() {
+ return mapFile;
+ }
+
+ public void setMapfile(String newMapfile) {
+ mapFile = newMapfile;
+ }
+
+}
diff --git a/src/cgeo/geocaching/cgeoinit.java b/src/cgeo/geocaching/cgeoinit.java
index 0be2093..d78a57d 100644
--- a/src/cgeo/geocaching/cgeoinit.java
+++ b/src/cgeo/geocaching/cgeoinit.java
@@ -21,6 +21,7 @@ import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
+import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;
@@ -31,6 +32,8 @@ import cgeo.geocaching.cgSettings.mapSourceEnum;
public class cgeoinit extends Activity {
+ private final int SELECT_MAPFILE_REQUEST=1;
+
private cgeoapplication app = null;
private Resources res = null;
private Activity activity = null;
@@ -402,8 +405,17 @@ public class cgeoinit extends Activity {
mapSourceSelector.setSelection(mapsource);
mapSourceSelector.setOnItemSelectedListener(new cgeoChangeMapSource());
- EditText mfmapFileEdit = (EditText) findViewById(R.id.mapfile);
- mfmapFileEdit.setText(prefs.getString("mfmapfile", ""));
+ initMapfileEdittext(false);
+
+ Button selectMapfile = (Button) findViewById(R.id.select_mapfile);
+ selectMapfile.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ Intent selectIntent = new Intent(activity, cgSelectMapfile.class);
+ activity.startActivityForResult(selectIntent, SELECT_MAPFILE_REQUEST);
+ }
+ });
setMapFileEditState();
@@ -418,6 +430,14 @@ public class cgeoinit extends Activity {
}
+ private void initMapfileEdittext(boolean setFocus) {
+ EditText mfmapFileEdit = (EditText) findViewById(R.id.mapfile);
+ mfmapFileEdit.setText(prefs.getString("mfmapfile", ""));
+ if (setFocus) {
+ mfmapFileEdit.requestFocus();
+ }
+ }
+
public void backup(View view) {
final String file = app.backupDatabase();
@@ -447,7 +467,7 @@ public class cgeoinit extends Activity {
}
private void setMapFileEditState() {
- EditText mapFileEdit = (EditText) findViewById(R.id.mapfile);
+ LinearLayout mapFileEdit = (LinearLayout) findViewById(R.id.init_mapfilegroup);
if (settings.mapProvider == mapSourceEnum.mapsforgeOffline) {
mapFileEdit.setVisibility(View.VISIBLE);
} else {
@@ -946,6 +966,20 @@ public class cgeoinit extends Activity {
}
}
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == SELECT_MAPFILE_REQUEST) {
+ if (resultCode == RESULT_OK) {
+ if (data.hasExtra("mapfile")) {
+ settings.setMapFile(data.getStringExtra("mapfile"));
+ }
+ }
+ initMapfileEdittext(true);
+ }
+ }
+
public void goHome(View view) {
base.goHome(activity);
}