/*
* Geopaparazzi - Digital field mapping on Android based devices
* Copyright (C) 2016 HydroloGIS (www.hydrologis.com)
*
* 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 eu.geopaparazzi.spatialite.database.spatial.activities.databasesview;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.RelativeLayout;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import eu.geopaparazzi.library.core.dialogs.ColorStrokeDialogFragment;
import eu.geopaparazzi.library.core.dialogs.LabelDialogFragment;
import eu.geopaparazzi.library.core.dialogs.StrokeDashDialogFragment;
import eu.geopaparazzi.library.core.dialogs.ZoomlevelDialogFragment;
import eu.geopaparazzi.library.core.maps.SpatialiteMap;
import eu.geopaparazzi.library.database.GPLog;
import eu.geopaparazzi.library.profiles.ProfilesHandler;
import eu.geopaparazzi.library.style.ColorStrokeObject;
import eu.geopaparazzi.library.style.ColorUtilities;
import eu.geopaparazzi.library.style.LabelObject;
import eu.geopaparazzi.library.util.AppsUtilities;
import eu.geopaparazzi.library.util.FileUtilities;
import eu.geopaparazzi.library.util.GPDialogs;
import eu.geopaparazzi.library.util.IActivitySupporter;
import eu.geopaparazzi.library.util.LibraryConstants;
import eu.geopaparazzi.library.util.StringAsyncTask;
import eu.geopaparazzi.library.util.Utilities;
import eu.geopaparazzi.library.util.types.ESpatialDataSources;
import eu.geopaparazzi.spatialite.R;
import eu.geopaparazzi.spatialite.database.spatial.SpatialiteSourcesManager;
import eu.geopaparazzi.spatialite.database.spatial.core.enums.TableTypes;
/**
* Activity for tile source visualisation.
*
* @author Andrea Antonello (www.hydrologis.com)
*/
public class SpatialiteDatabasesTreeListActivity extends AppCompatActivity implements IActivitySupporter,
LabelDialogFragment.ILabelPropertiesChangeListener, ColorStrokeDialogFragment.IColorStrokePropertiesChangeListener,
StrokeDashDialogFragment.IDashStrokePropertiesChangeListener, ZoomlevelDialogFragment.IZoomlevelPropertiesChangeListener {
public static final int PICKFILE_REQUEST_CODE = 666;
public static final int PICKFOLDER_REQUEST_CODE = 667;
public static final String SHOW_TABLES = "showTables";
public static final String SHOW_VIEWS = "showViews";
private ExpandableListView mExpListView;
private EditText mFilterText;
private String mTextToFilter = "";
private SharedPreferences mPreferences;
private boolean[] mCheckedValues;
private List<String> mTypeNames;
private final LinkedHashMap<String, List<SpatialiteMap>> newMap = new LinkedHashMap<>();
private SpatialiteDatabasesExpandableListAdapter expandableListAdapter;
private StringAsyncTask loadDataTask;
private StringAsyncTask addNewSourceTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.spatialitedatabases_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
mFilterText = (EditText) findViewById(R.id.search_box);
mFilterText.addTextChangedListener(filterTextWatcher);
boolean showTables = mPreferences.getBoolean(SHOW_TABLES, true);
boolean showViews = mPreferences.getBoolean(SHOW_VIEWS, true);
String tableTypeName = TableTypes.SPATIALTABLE.getDescription();
String viewTypeName = TableTypes.SPATIALVIEW.getDescription();
mTypeNames = new ArrayList<>();
mTypeNames.add(tableTypeName);
mTypeNames.add(viewTypeName);
mCheckedValues = new boolean[mTypeNames.size()];
mCheckedValues[0] = showTables;
mCheckedValues[1] = showViews;
// get the listview
mExpListView = (ExpandableListView) findViewById(R.id.expandableSourceListView);
if (ProfilesHandler.INSTANCE.getActiveProfile() != null) {
RelativeLayout mainView = (RelativeLayout) findViewById(R.id.sources_list_mainview);
int color = ColorUtilities.toColor(ProfilesHandler.INSTANCE.getActiveProfile().color);
mainView.setBackgroundColor(color);
FloatingActionButton addSourceButton = (FloatingActionButton) findViewById(R.id.addSourceButton);
addSourceButton.hide();
}
loadDataTask = new StringAsyncTask(this) {
List<SpatialiteMap> spatialiteMaps;
protected String doBackgroundWork() {
spatialiteMaps = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps();
return "";
}
protected void doUiPostWork(String response) {
dispose();
try {
refreshData(spatialiteMaps);
} catch (Exception e) {
GPLog.error(this, "Problem getting databases.", e);
}
}
};
loadDataTask.setProgressDialog("", getString(R.string.loading_databases), false, null);
loadDataTask.execute();
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onDestroy() {
if (loadDataTask != null) loadDataTask.dispose();
if (addNewSourceTask != null) addNewSourceTask.dispose();
super.onDestroy();
}
@Override
protected void onStop() {
mFilterText.removeTextChangedListener(filterTextWatcher);
// save changes to preferences also
SpatialiteSourcesManager.INSTANCE.saveCurrentSpatialiteMapsToPreferences();
super.onStop();
}
public void add(View view) {
try {
String title = getString(R.string.select_spatialite_database);
String[] supportedExtensions = ESpatialDataSources.getSupportedVectorExtensions();
AppsUtilities.pickFile(this, PICKFILE_REQUEST_CODE, title, supportedExtensions, null);
} catch (Exception e) {
GPLog.error(this, null, e);
GPDialogs.errorDialog(this, e, null);
}
}
public void addFolder(View view) {
try {
String title = getString(R.string.select_spatialite_database_folder);
String[] supportedExtensions = ESpatialDataSources.getSupportedVectorExtensions();
AppsUtilities.pickFolder(this, PICKFOLDER_REQUEST_CODE, title, null, supportedExtensions);
} catch (Exception e) {
GPLog.error(this, null, e);
GPDialogs.errorDialog(this, e, null);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case (PICKFILE_REQUEST_CODE): {
if (resultCode == Activity.RESULT_OK) {
try {
String filePath = data.getStringExtra(LibraryConstants.PREFS_KEY_PATH);
final File file = new File(filePath);
if (file.exists()) {
Utilities.setLastFilePath(this, filePath);
// add basemap to list and in mPreferences
addNewSourceTask = new StringAsyncTask(this) {
public List<SpatialiteMap> spatialiteMaps;
protected String doBackgroundWork() {
try {
// add basemap to list and in mPreferences
if (SpatialiteSourcesManager.INSTANCE.addSpatialiteMapFromFile(file)) {
spatialiteMaps = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps();
} else {
return getString(R.string.selected_file_no_vector_data) + file.getAbsolutePath();
}
} catch (Exception e) {
GPLog.error(this, "Problem getting sources.", e);
return "ERROR: " + e.getLocalizedMessage();
}
return "";
}
protected void doUiPostWork(String response) {
dispose();
if (response.length() > 0) {
GPDialogs.warningDialog(SpatialiteDatabasesTreeListActivity.this, response, null);
} else {
try {
refreshData(spatialiteMaps);
} catch (Exception e) {
GPLog.error(this, null, e);
}
}
}
};
addNewSourceTask.setProgressDialog("", getString(R.string.adding_new_source), false, null);
addNewSourceTask.execute();
}
} catch (Exception e) {
GPDialogs.errorDialog(this, e, null);
}
}
break;
}
case (PICKFOLDER_REQUEST_CODE): {
if (resultCode == Activity.RESULT_OK) {
try {
String folderPath = data.getStringExtra(LibraryConstants.PREFS_KEY_PATH);
final File folder = new File(folderPath);
if (folder.exists()) {
Utilities.setLastFilePath(this, folderPath);
final List<File> foundFiles = new ArrayList<>();
// get all supported files
String[] supportedExtensions = ESpatialDataSources.getSupportedVectorExtensions();
FileUtilities.searchDirectoryRecursive(folder, supportedExtensions, foundFiles);
// add basemap to list and in mPreferences
addNewSourceTask = new StringAsyncTask(this) {
public List<SpatialiteMap> spatialiteMaps;
protected String doBackgroundWork() {
try {
for (int i = 0; i < foundFiles.size(); i++) {
File file = foundFiles.get(i);
try {
// add basemap to list and in mPreferences
SpatialiteSourcesManager.INSTANCE.addSpatialiteMapFromFile(file);
} catch (Exception e) {
// ignore
} finally {
onProgressUpdate(i + 1);
}
}
spatialiteMaps = SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps();
if (spatialiteMaps.size() == 0) {
return getString(R.string.selected_file_no_vector_data) + folder.getAbsolutePath();
}
} catch (Exception e) {
GPLog.error(this, "Problem getting sources.", e);
return "ERROR: " + e.getLocalizedMessage();
}
return "";
}
protected void doUiPostWork(String response) {
dispose();
if (response.length() > 0) {
GPDialogs.warningDialog(SpatialiteDatabasesTreeListActivity.this, response, null);
} else {
try {
refreshData(spatialiteMaps);
} catch (Exception e) {
GPLog.error(this, null, e);
}
}
}
};
addNewSourceTask.setProgressDialog("", getString(R.string.adding_new_source), false, foundFiles.size());
addNewSourceTask.execute();
}
} catch (Exception e) {
GPDialogs.errorDialog(this, e, null);
}
}
break;
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_spatialitedatabases, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.select_type_item) {
TableTypesChoiceDialog dialog = new TableTypesChoiceDialog();
dialog.open(getString(R.string.select_type), SpatialiteDatabasesTreeListActivity.this, mTypeNames, mCheckedValues);
}
return super.onOptionsItemSelected(item);
}
public void refreshData(List<SpatialiteMap> spatialiteMaps) throws Exception {
SharedPreferences.Editor editor = mPreferences.edit();
editor.putBoolean(SHOW_TABLES, mCheckedValues[0]);
editor.putBoolean(SHOW_VIEWS, mCheckedValues[1]);
editor.apply();
boolean log = GPLog.LOG;
if (log) {
GPLog.addLogEntry(this, "Available spatialitemaps:");
for (SpatialiteMap tmpSpatialiteMap : spatialiteMaps) {
GPLog.addLogEntry(this, tmpSpatialiteMap.toString());
}
}
newMap.clear();
for (SpatialiteMap spatialiteMap : spatialiteMaps) {
String key = spatialiteMap.databasePath;
List<SpatialiteMap> newValues = newMap.get(key);
if (newValues == null) {
newValues = new ArrayList<>();
newMap.put(key, newValues);
}
boolean doAdd = false;
String tableType = spatialiteMap.tableType;
if (tableType == null) {
doAdd = true;
} else if (mCheckedValues[0] && tableType.equals(TableTypes.SPATIALTABLE.getDescription())) {
doAdd = true;
} else if (mCheckedValues[1] && tableType.equals(TableTypes.SPATIALVIEW.getDescription())) {
doAdd = true;
}
if (log) {
GPLog.addLogEntry(this, "doAdd: " + doAdd + " spatialiteMap: " + spatialiteMap);
}
if (mTextToFilter.length() > 0) {
// filter text
String filterString = mTextToFilter.toLowerCase();
String valueString = spatialiteMap.databasePath.toLowerCase();
if (!valueString.contains(filterString)) {
valueString = spatialiteMap.tableName.toLowerCase();
if (!valueString.contains(filterString)) {
doAdd = false;
}
}
}
if (doAdd) {
newValues.add(spatialiteMap);
if (log) {
GPLog.addLogEntry(this, "Added: " + spatialiteMap.toString());
}
}
if (newValues.size() == 0) {
newMap.remove(key);
}
}
expandableListAdapter = new SpatialiteDatabasesExpandableListAdapter(this, newMap);
mExpListView.setAdapter(expandableListAdapter);
mExpListView.setClickable(true);
mExpListView.setFocusable(true);
mExpListView.setFocusableInTouchMode(true);
// mExpListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
// public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
// int index = 0;
// SpatialiteMap selectedSpatialiteMap = null;
// for (Entry<String, List<SpatialiteMap>> entry : newMap.entrySet()) {
// if (groupPosition == index) {
// List<SpatialiteMap> value = entry.getValue();
// selectedSpatialiteMap = value.get(childPosition);
// break;
// }
// index++;
// }
// try {
// SpatialiteSourcesManager.INSTANCE.setSelectedBaseMap(selectedSpatialiteMap);
// } catch (jsqlite.Exception e) {
// GPLog.error(SourcesTreeListActivity.this, "ERROR", e);
// }
// finish();
// return false;
// }
// });
if (ProfilesHandler.INSTANCE.getActiveProfile() == null)
mExpListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
int groupPosition = ExpandableListView.getPackedPositionGroup(id);
int index = 0;
for (final String group : newMap.keySet()) {
if (index == groupPosition) {
GPDialogs.yesNoMessageDialog(SpatialiteDatabasesTreeListActivity.this, String.format(getString(R.string.remove_from_list), group), new Runnable() {
@Override
public void run() {
List<SpatialiteMap> spatialiteMapList = newMap.get(group);
try {
SpatialiteSourcesManager.INSTANCE.removeSpatialiteMaps(spatialiteMapList);
} catch (Exception e) {
GPLog.error(this, null, e);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
refreshData(SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps());
} catch (Exception e) {
GPLog.error(this, null, e);
}
}
});
}
}, null);
return true;
}
index++;
}
return true;
}
// if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
// int groupPosition = ExpandableListView.getPackedPositionGroup(id);
// int childPosition = ExpandableListView.getPackedPositionChild(id);
//
// int index = 0;
// for (String group : newMap.keySet()) {
// if (index == groupPosition) {
// List<SpatialiteMap> spatialiteMapList = newMap.get(group);
//
//
// final SpatialiteMap spatialiteMap = spatialiteMapList.get(childPosition);
//
// GPDialogs.yesNoMessageDialog(SpatialiteDatabasesTreeListActivity.this, String.format(getString(R.string.remove_from_list), spatialiteMap.title), new Runnable() {
// @Override
// public void run() {
// try {
// SpatialiteSourcesManager.INSTANCE.removeSpatialiteMap(spatialiteMap);
// } catch (JSONException e) {
// GPLog.error(this, null, e);
// }
//
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
// try {
// refreshData(SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps());
// } catch (Exception e) {
// GPLog.error(this, null, e);
// }
// }
// });
//
// }
// }, null);
//
// return true;
// }
// index++;
// }
// return true;
// }
return false;
}
});
int groupCount = expandableListAdapter.getGroupCount();
for (int i = 0; i < groupCount; i++) {
mExpListView.expandGroup(i);
}
}
public void onPropertiesChanged(ColorStrokeObject newColorStrokeObject) {
if (expandableListAdapter != null)
expandableListAdapter.onPropertiesChanged(newColorStrokeObject);
}
public void onPropertiesChanged(LabelObject newLabelObject) {
if (expandableListAdapter != null)
expandableListAdapter.onPropertiesChanged(newLabelObject);
}
@Override
public void onDashChanged(float[] dash, float shift) {
if (expandableListAdapter != null)
expandableListAdapter.onDashChanged(dash, shift);
}
@Override
public void onPropertiesChanged(int minZoomlevel, int maxZoomlevel) {
if (expandableListAdapter != null)
expandableListAdapter.onPropertiesChanged(minZoomlevel, maxZoomlevel);
}
private TextWatcher filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
// ignore
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// ignore
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
mTextToFilter = s.toString();
try {
refreshData(SpatialiteSourcesManager.INSTANCE.getSpatialiteMaps());
} catch (Exception e) {
GPLog.error(SpatialiteDatabasesTreeListActivity.this, "ERROR", e);
}
}
};
@Override
public Context getContext() {
return this;
}
}