package net.osmand.plus.osmedit; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; import net.osmand.PlatformUtil; import net.osmand.data.Amenity; import net.osmand.osm.PoiType; import net.osmand.osm.edit.Node; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter.ItemClickListener; import net.osmand.plus.ContextMenuItem; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.EnumAdapter; import net.osmand.plus.activities.EnumAdapter.IEnumWithResource; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.TabActivity; import net.osmand.plus.dashboard.tools.DashFragmentData; import net.osmand.plus.myplaces.AvailableGPXFragment; import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo; import net.osmand.plus.myplaces.FavoritesActivity; import net.osmand.plus.osmedit.OsmPoint.Action; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; import java.util.List; public class OsmEditingPlugin extends OsmandPlugin { private static final Log LOG = PlatformUtil.getLog(OsmEditingPlugin.class); private static final String ID = "osm.editing"; private OsmandSettings settings; private OsmandApplication app; private OpenstreetmapsDbHelper dbpoi; private OsmBugsDbHelper dbbug; private OpenstreetmapLocalUtil localUtil; private OpenstreetmapRemoteUtil remoteUtil; private OsmBugsRemoteUtil remoteNotesUtil; private OsmBugsLocalUtil localNotesUtil; public OsmEditingPlugin(OsmandApplication app) { this.app = app; settings = app.getSettings(); } @Override public String getId() { return ID; } public OpenstreetmapsDbHelper getDBPOI() { if (dbpoi == null) { dbpoi = new OpenstreetmapsDbHelper(app); } return dbpoi; } public OpenstreetmapLocalUtil getPoiModificationLocalUtil() { if (localUtil == null) { localUtil = new OpenstreetmapLocalUtil(this); } return localUtil; } public OpenstreetmapRemoteUtil getPoiModificationRemoteUtil() { if (remoteUtil == null) { remoteUtil = new OpenstreetmapRemoteUtil(app); } return remoteUtil; } public OsmBugsRemoteUtil getOsmNotesRemoteUtil() { if (remoteNotesUtil == null) { remoteNotesUtil = new OsmBugsRemoteUtil(app); } return remoteNotesUtil; } public OsmBugsLocalUtil getOsmNotesLocalUtil() { if (localNotesUtil == null) { localNotesUtil = new OsmBugsLocalUtil(app, getDBBug()); } return localNotesUtil; } public OsmBugsDbHelper getDBBug() { if (dbbug == null) { dbbug = new OsmBugsDbHelper(app); } return dbbug; } private OsmBugsLayer osmBugsLayer; private OsmEditsLayer osmEditsLayer; // private EditingPOIDialogProvider poiActions; @Override public void updateLayers(OsmandMapTileView mapView, MapActivity activity) { if (isActive()) { if (osmBugsLayer == null) { registerLayers(activity); } if (!mapView.getLayers().contains(osmEditsLayer)) { activity.getMapView().addLayer(osmEditsLayer, 3.5f); } if (mapView.getLayers().contains(osmBugsLayer) != settings.SHOW_OSM_BUGS.get()) { if (settings.SHOW_OSM_BUGS.get()) { mapView.addLayer(osmBugsLayer, 2); } else { mapView.removeLayer(osmBugsLayer); } } } else { if (osmBugsLayer != null) { mapView.removeLayer(osmBugsLayer); } if (osmEditsLayer != null) { mapView.removeLayer(osmEditsLayer); } } } @Override public void registerLayers(MapActivity activity) { osmBugsLayer = new OsmBugsLayer(activity, this); osmEditsLayer = new OsmEditsLayer(activity, this); } public OsmEditsLayer getOsmEditsLayer(MapActivity activity) { if (osmEditsLayer == null) { registerLayers(activity); } return osmEditsLayer; } public OsmBugsLayer getBugsLayer(MapActivity activity) { if (osmBugsLayer == null) { registerLayers(activity); } return osmBugsLayer; } @Override public Class<? extends Activity> getSettingsActivity() { return SettingsOsmEditingActivity.class; } @Override public void registerMapContextMenuActions(final MapActivity mapActivity, final double latitude, final double longitude, ContextMenuAdapter adapter, final Object selectedObj) { ContextMenuAdapter.ItemClickListener listener = new ContextMenuAdapter.ItemClickListener() { @Override public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int resId, int pos, boolean isChecked) { if (resId == R.string.context_menu_item_create_poi) { //getPoiActions(mapActivity).showCreateDialog(latitude, longitude); EditPoiDialogFragment editPoiDialogFragment = EditPoiDialogFragment.createAddPoiInstance(latitude, longitude, mapActivity.getMyApplication()); editPoiDialogFragment.show(mapActivity.getSupportFragmentManager(), EditPoiDialogFragment.TAG); } else if (resId == R.string.context_menu_item_open_note) { openOsmNote(mapActivity, latitude, longitude); } else if (resId == R.string.poi_context_menu_delete) { new EditPoiDialogFragment.ShowDeleteDialogAsyncTask(mapActivity) .execute((Amenity) selectedObj); } else if (resId == R.string.poi_context_menu_modify) { EditPoiDialogFragment.showEditInstance((Amenity) selectedObj, mapActivity); } else if (resId == R.string.poi_context_menu_modify_osm_change) { final Node entity = ((OpenstreetmapPoint) selectedObj).getEntity(); EditPoiDialogFragment.createInstance(entity, false) .show(mapActivity.getSupportFragmentManager(), EditPoiDialogFragment.TAG); } return true; } }; boolean isEditable = false; if (selectedObj instanceof Amenity) { Amenity amenity = (Amenity) selectedObj; final PoiType poiType = amenity.getType().getPoiTypeByKeyName(amenity.getSubType()); isEditable = !amenity.getType().isWiki() && poiType !=null && !poiType.isNotEditableOsm(); } if (isEditable) { adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.poi_context_menu_modify, mapActivity) .setIcon(R.drawable.ic_action_edit_dark) .setListener(listener) .createItem()); adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.poi_context_menu_delete, mapActivity) .setIcon(R.drawable.ic_action_delete_dark) .setListener(listener) .createItem()); } else if (selectedObj instanceof OpenstreetmapPoint && ((OpenstreetmapPoint) selectedObj).getAction() != Action.DELETE) { adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.poi_context_menu_modify_osm_change, mapActivity) .setIcon(R.drawable.ic_action_edit_dark) .setListener(listener) .createItem()); } else { adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.context_menu_item_create_poi, mapActivity) .setIcon(R.drawable.ic_action_plus_dark) .setListener(listener) .createItem()); } adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.context_menu_item_open_note, mapActivity) .setIcon(R.drawable.ic_action_bug_dark) .setListener(listener).createItem()); } public void openOsmNote(MapActivity mapActivity, double latitude, double longitude) { if (osmBugsLayer == null) { registerLayers(mapActivity); } osmBugsLayer.openBug(latitude, longitude, ""); } public void openOsmNote(MapActivity mapActivity, double latitude, double longitude, String message, boolean autofill) { if (osmBugsLayer == null) { registerLayers(mapActivity); } osmBugsLayer.openBug(latitude, longitude, message, autofill); } @Override public void addMyPlacesTab(FavoritesActivity favoritesActivity, List<TabActivity.TabItem> mTabs, Intent intent) { if (getDBPOI().getOpenstreetmapPoints().size() > 0 || getDBBug().getOsmbugsPoints().size() > 0) { mTabs.add(favoritesActivity.getTabIndicator(R.string.osm_edits, OsmEditsFragment.class)); if (intent != null && "OSM".equals(intent.getStringExtra("TAB"))) { app.getSettings().FAVORITES_TAB.set(R.string.osm_edits); } } } @Override public void registerLayerContextMenuActions(OsmandMapTileView mapView, ContextMenuAdapter adapter, final MapActivity mapActivity) { adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.layer_osm_bugs, mapActivity) .setSelected(settings.SHOW_OSM_BUGS.get()) .setIcon(R.drawable.ic_action_bug_dark) .setColor(settings.SHOW_OSM_BUGS.get() ? R.color.osmand_orange : ContextMenuItem.INVALID_ID) .setListener(new ContextMenuAdapter.ItemClickListener() { @Override public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) { if (itemId == R.string.layer_osm_bugs) { OsmandSettings.OsmandPreference<Boolean> showOsmBugs = settings.SHOW_OSM_BUGS; showOsmBugs.set(isChecked); adapter.getItem(pos).setColorRes(showOsmBugs.get() ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); adapter.notifyDataSetChanged(); updateLayers(mapActivity.getMapView(), mapActivity); } return true; } }) .setPosition(16) .createItem()); } @Override public String getDescription() { return app.getString(R.string.osm_editing_plugin_description); } @Override public void contextMenuFragment(final Activity la, final Fragment fragment, final Object info, ContextMenuAdapter adapter) { if (fragment instanceof AvailableGPXFragment) { adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.local_index_mi_upload_gpx, la) .setIcon(R.drawable.ic_action_export) .setListener(new ContextMenuAdapter.ItemClickListener() { @Override public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) { sendGPXFiles(la, (AvailableGPXFragment) fragment, (GpxInfo) info); return true; } }).createItem()); } } @Override public void optionsMenuFragment(final Activity activity, final Fragment fragment, ContextMenuAdapter optionsMenuAdapter) { if (fragment instanceof AvailableGPXFragment) { final AvailableGPXFragment f = ((AvailableGPXFragment) fragment); optionsMenuAdapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.local_index_mi_upload_gpx, activity) .setIcon(R.drawable.ic_action_export) .setColor(R.color.color_white) .setListener(new ItemClickListener() { @Override public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) { f.openSelectionMode(R.string.local_index_mi_upload_gpx, R.drawable.ic_action_export, R.drawable.ic_action_export, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { List<GpxInfo> selectedItems = f.getSelectedItems(); sendGPXFiles(activity, f, selectedItems.toArray(new GpxInfo[selectedItems.size()])); } }); return true; } }) .setPosition(5) .createItem()); } } public enum UploadVisibility implements IEnumWithResource { Public(R.string.gpxup_public), Identifiable(R.string.gpxup_identifiable), Trackable(R.string.gpxup_trackable), Private(R.string.gpxup_private); private final int resourceId; UploadVisibility(int resourceId) { this.resourceId = resourceId; } public String asURLparam() { return name().toLowerCase(); } @Override public int stringResource() { return resourceId; } } public boolean sendGPXFiles(final Activity la, AvailableGPXFragment f, final GpxInfo... info) { String name = settings.USER_NAME.get(); String pwd = settings.USER_PASSWORD.get(); if (Algorithms.isEmpty(name) || Algorithms.isEmpty(pwd)) { Toast.makeText(la, R.string.validate_gpx_upload_name_pwd, Toast.LENGTH_LONG).show(); return false; } AlertDialog.Builder bldr = new AlertDialog.Builder(la); LayoutInflater inflater = (LayoutInflater) la.getSystemService(Context.LAYOUT_INFLATER_SERVICE); final View view = inflater.inflate(R.layout.send_gpx_osm, null); final EditText descr = (EditText) view.findViewById(R.id.memory_size); if (info.length > 0 && info[0].getFileName() != null) { int dt = info[0].getFileName().indexOf('.'); descr.setText(info[0].getFileName().substring(0, dt)); } final EditText tags = (EditText) view.findViewById(R.id.TagsText); final Spinner visibility = ((Spinner) view.findViewById(R.id.Visibility)); EnumAdapter<UploadVisibility> adapter = new EnumAdapter<>(la, android.R.layout.simple_spinner_item, UploadVisibility.values()); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); visibility.setAdapter(adapter); visibility.setSelection(0); bldr.setView(view); bldr.setNegativeButton(R.string.shared_string_no, null); bldr.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { new UploadGPXFilesTask(la, descr.getText().toString(), tags.getText().toString(), (UploadVisibility) visibility.getItemAtPosition(visibility.getSelectedItemPosition()) ).execute(info); } }); bldr.show(); return true; } @Override public String getName() { return app.getString(R.string.osm_settings); } @Override public int getLogoResourceId() { return R.drawable.ic_action_bug_dark; } @Override public int getAssetResourceName() { return R.drawable.osm_editing; } @Override public String getHelpFileName() { return "feature_articles/osm-editing-plugin.html"; } public static String getEditName(OsmPoint point) { String prefix = getPrefix(point); if (point.getGroup() == OsmPoint.Group.POI) { String subtype = ""; if (!Algorithms.isEmpty(((OpenstreetmapPoint) point).getSubtype())) { subtype = " (" + ((OpenstreetmapPoint) point).getSubtype() + ") "; } return prefix + subtype + ((OpenstreetmapPoint) point).getName(); } else if (point.getGroup() == OsmPoint.Group.BUG) { return prefix + ((OsmNotesPoint) point).getText(); } else { return prefix; } } private static String getPrefix(OsmPoint osmPoint) { return (osmPoint.getGroup() == OsmPoint.Group.POI ? "POI " : "Bug ") + " id: " + osmPoint.getId() + " "; } @Override public DashFragmentData getCardFragment() { return DashOsmEditsFragment.FRAGMENT_DATA; } }