/*
* Copyright (C) 2012 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.profiles;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationGroup;
import android.app.ProfileManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
public class AppGroupConfig extends SettingsPreferenceFragment
implements Preference.OnPreferenceChangeListener {
private static String TAG = "AppGroupConfig";
private static final int DIALOG_APPS = 0;
private static final int DELETE_CONFIRM = 1;
private static final int DELETE_GROUP_CONFIRM = 2;
public static final String PROFILE_SERVICE = "profile";
private ListView mListView;
private PackageManager mPackageManager;
private List<PackageInfo> mInstalledPackages;
private NotificationGroup mNotificationGroup;
private ProfileManager mProfileManager;
private NamePreference mNamePreference;
private static final int MENU_DELETE = Menu.FIRST;
private static final int MENU_ADD = Menu.FIRST + 1;
PackageAdaptor mAppAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mProfileManager = (ProfileManager) getActivity().getSystemService(PROFILE_SERVICE);
addPreferencesFromResource(R.xml.application_list);
final Bundle args = getArguments();
if (args != null) {
mNotificationGroup = (NotificationGroup) args.getParcelable("NotificationGroup");
mPackageManager = getPackageManager();
mInstalledPackages = mPackageManager.getInstalledPackages(0);
mAppAdapter = new PackageAdaptor(mInstalledPackages);
mAppAdapter.update();
updatePackages();
setHasOptionsMenu(true);
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem delete = menu.add(0, MENU_DELETE, 0, R.string.profile_menu_delete)
.setIcon(R.drawable.ic_menu_trash_holo_dark);
delete.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
MenuItem addApplication = menu.add(0, MENU_ADD, 0, R.string.profiles_add)
.setIcon(R.drawable.ic_menu_add)
.setAlphabeticShortcut('a');
addApplication.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_DELETE:
deleteNotificationGroup();
return true;
case MENU_ADD:
addNewApp();
return true;
default:
return false;
}
}
Preference mAddPreference;
Preference mDeletePreference;
private void updatePackages() {
PreferenceScreen prefSet = getPreferenceScreen();
// Add the General section
PreferenceGroup generalPrefs = (PreferenceGroup) prefSet.findPreference("general_section");
if (generalPrefs != null) {
generalPrefs.removeAll();
// Name preference
mNamePreference = new NamePreference(getActivity(), mNotificationGroup.getName());
mNamePreference.setOnPreferenceChangeListener(this);
generalPrefs.addPreference(mNamePreference);
}
PreferenceGroup applicationsList = (PreferenceGroup) prefSet.findPreference("applications_list");
if (applicationsList != null) {
applicationsList.removeAll();
for (String pkg : mNotificationGroup.getPackages()) {
Preference pref = new Preference(getActivity());
try {
PackageInfo group = mPackageManager.getPackageInfo(pkg, 0);
pref.setKey(group.packageName);
pref.setTitle(group.applicationInfo.loadLabel(mPackageManager));
Drawable icon = group.applicationInfo.loadIcon(mPackageManager);
pref.setIcon(icon);
pref.setSelectable(true);
pref.setPersistent(false);
applicationsList.addPreference(pref);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
menu.add(0, R.string.profile_menu_delete, 0, R.string.profile_menu_delete);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo aMenuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
PackageItem selectedGroup = (PackageItem) mListView.getItemAtPosition(aMenuInfo.position);
switch (item.getItemId()) {
case R.string.profile_menu_delete:
deleteAppFromGroup(selectedGroup);
return true;
}
return super.onOptionsItemSelected(item);
}
private void deleteAppFromGroup(PackageItem selectedGroup) {
if (selectedGroup != null) {
mNotificationGroup.removePackage(selectedGroup.packageName);
updatePackages();
}
}
@Override
public void onPause() {
if (mNotificationGroup != null) {
mProfileManager.addNotificationGroup(mNotificationGroup);
}
super.onPause();
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mNamePreference) {
String name = mNamePreference.getName().toString();
if (!name.equals(mNotificationGroup.getName())) {
if (!mProfileManager.notificationGroupExists(name)) {
mNotificationGroup.setName(name);
} else {
mNamePreference.setName(mNotificationGroup.getName());
Toast.makeText(getActivity(), R.string.duplicate_appgroup_name, Toast.LENGTH_LONG).show();
}
}
}
return true;
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference instanceof Preference) {
String deleteItem = preference.getKey();
removeApp(deleteItem);
return true;
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
private void addNewApp() {
showDialog(DIALOG_APPS);
// TODO: switch to using the built in app list rather than dialog box?
}
private void removeApp(String key) {
mPackageToDelete = key.toString();
showDialog(DELETE_CONFIRM);
}
private void deleteNotificationGroup() {
showDialog(DELETE_GROUP_CONFIRM);
}
@Override
public Dialog onCreateDialog(int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final Dialog dialog;
switch (id) {
case DIALOG_APPS:
final ListView list = new ListView(getActivity());
list.setAdapter(mAppAdapter);
builder.setTitle(R.string.profile_choose_app);
builder.setView(list);
dialog = builder.create();
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PackageItem info = (PackageItem) parent.getItemAtPosition(position);
mNotificationGroup.addPackage(info.packageName);
updatePackages();
dialog.cancel();
}
});
break;
case DELETE_CONFIRM:
builder.setMessage(R.string.profile_app_delete_confirm);
builder.setTitle(R.string.profile_menu_delete);
builder.setIconAttribute(android.R.attr.alertDialogIcon);
builder.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
doDelete();
}
});
builder.setNegativeButton(android.R.string.no,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog = builder.create();
break;
case DELETE_GROUP_CONFIRM:
builder.setMessage(R.string.profile_delete_appgroup);
builder.setTitle(R.string.profile_menu_delete);
builder.setIconAttribute(android.R.attr.alertDialogIcon);
builder.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mProfileManager.removeNotificationGroup(mNotificationGroup);
mNotificationGroup = null;
finish();
}
});
builder.setNegativeButton(android.R.string.no,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
}
String mPackageToDelete;
private void doDelete() {
mNotificationGroup.removePackage(mPackageToDelete);
updatePackages();
}
class PackageItem implements Comparable<PackageItem> {
CharSequence title;
String packageName;
Drawable icon;
@Override
public int compareTo(PackageItem another) {
return this.title.toString().compareTo(another.title.toString());
}
}
class PackageAdaptor extends BaseAdapter {
protected List<PackageInfo> mInstalledPackageInfo;
protected List<PackageItem> mInstalledPackages = new LinkedList<PackageItem>();
private void reloadList() {
final Handler handler = new Handler();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (mInstalledPackages) {
mInstalledPackages.clear();
for (PackageInfo info : mInstalledPackageInfo) {
final PackageItem item = new PackageItem();
ApplicationInfo applicationInfo = info.applicationInfo;
item.title = applicationInfo.loadLabel(mPackageManager);
item.icon = applicationInfo.loadIcon(mPackageManager);
item.packageName = applicationInfo.packageName;
handler.post(new Runnable() {
@Override
public void run() {
int index = Collections.binarySearch(mInstalledPackages, item);
if (index < 0) {
index = -index - 1;
mInstalledPackages.add(index, item);
}
notifyDataSetChanged();
}
});
}
}
}
}).start();
}
public PackageAdaptor(List<PackageInfo> installedPackagesInfo) {
mInstalledPackageInfo = installedPackagesInfo;
}
public void update() {
reloadList();
}
@Override
public int getCount() {
return mInstalledPackages.size();
}
@Override
public PackageItem getItem(int position) {
return mInstalledPackages.get(position);
}
@Override
public long getItemId(int position) {
return mInstalledPackages.get(position).packageName.hashCode();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView != null) {
holder = (ViewHolder) convertView.getTag();
} else {
final LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.preference_icon, null, false);
holder = new ViewHolder();
convertView.setTag(holder);
holder.title = (TextView) convertView.findViewById(com.android.internal.R.id.title);
holder.summary = (TextView) convertView
.findViewById(com.android.internal.R.id.summary);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
}
PackageItem applicationInfo = getItem(position);
if (holder.title != null) {
holder.title.setText(applicationInfo.title);
}
if (holder.summary != null) {
holder.summary.setVisibility(View.GONE);
}
if (holder.icon != null) {
Drawable loadIcon = applicationInfo.icon;
holder.icon.setImageDrawable(loadIcon);
}
return convertView;
}
}
static class ViewHolder {
TextView title;
TextView summary;
ImageView icon;
}
}