/*
* TV-Browser for Android
* Copyright (C) 2013 René Mach (rene@tvbrowser.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to use, copy, modify or merge the Software,
* furthermore to publish and distribute the Software free of charge without modifications and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.tvbrowser.tvbrowser;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;
import org.tvbrowser.content.TvBrowserContentProvider;
import org.tvbrowser.settings.SettingConstants;
import org.tvbrowser.tvbrowser.LoaderUpdater.UnsupportedFragmentException;
import org.tvbrowser.utils.CompatUtils;
import org.tvbrowser.utils.IOUtils;
import org.tvbrowser.utils.PrefUtils;
import org.tvbrowser.utils.ProgramUtils;
import org.tvbrowser.utils.UiUtils;
import org.tvbrowser.view.SeparatorDrawable;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
public class FragmentProgramsList extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, OnSharedPreferenceChangeListener, ShowDateInterface, ShowChannelInterface, MarkingsUpdateListener {
public static final int NO_CHANNEL_SELECTION_ID = -1;
public static final int INDEX_DATE_TODAY = 3;
public static final int INDEX_DATE_YESTERDAY = 2;
public static final int INDEX_DATE_TODAY_TOMORROW = 0;
private static final String EXTRA_NEXT_UPDATE = "EXTRA_NEXT_UPDATE";
private SimpleCursorAdapter mProgramListAdapter;
private Handler handler;
private LoaderUpdater mLoaderUpdate;
//private boolean mKeepRunning;
//private Thread mUpdateThread;
private long mChannelID;
private long mScrollTime;
private long mDayStart;
private String mDayClause;
private WhereClause mFilterClause;
private ProgramListViewBinderAndClickHandler mViewAndClickHandler;
private BroadcastReceiver mDataUpdateReceiver;
private BroadcastReceiver mRefreshReceiver;
private BroadcastReceiver mDontWantToSeeReceiver;
private BroadcastReceiver mMarkingsChangedReceiver;
private BroadcastReceiver mChannelUpdateReceiver;
//private boolean mDontUpdate;
private int mScrollPos;
private ListView mListView;
private long mCursorLoadLastTime = 0;
private long mNextUpdate = 0;
private Spinner mChannelSelection;
private ArrayAdapter<DateSelection> mDateAdapter;
private Spinner mDateSelection;
private int mDayPreSelection = -1;
public FragmentProgramsList() {
this(NO_CHANNEL_SELECTION_ID,-1);
}
public FragmentProgramsList(int channelId, long startTime) {
this(channelId, startTime, -1);
}
public FragmentProgramsList(int channelId, long startTime, long endTime) {
mScrollTime = startTime;
mChannelID = channelId;
mScrollPos = -1;
if(endTime != -1 && endTime < System.currentTimeMillis()) {
Calendar now = Calendar.getInstance();
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
if(startTime < now.getTimeInMillis()) {
mDayPreSelection = INDEX_DATE_YESTERDAY;
}
else {
mDayPreSelection = INDEX_DATE_TODAY;
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new Handler();
try {
mLoaderUpdate = new LoaderUpdater(FragmentProgramsList.this, handler);
} catch (UnsupportedFragmentException e) {
// Ignore
}
}
@Override
public void onResume() {
super.onResume();
mLoaderUpdate.setIsRunning();
ProgramUtils.registerMarkingsListener(getActivity(), this);
if(mDayPreSelection == -1 || mDateAdapter.getCount() < mDayPreSelection) {
mLoaderUpdate.startUpdate(mNextUpdate);
}
else {
mDateSelection.setSelection(mDayPreSelection);
}
}
@Override
public void onPause() {
ProgramUtils.unregisterMarkingsListener(getActivity(), this);
mLoaderUpdate.setIsNotRunning();
super.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong(EXTRA_NEXT_UPDATE, mNextUpdate);
}
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
if(savedInstanceState != null) {
mNextUpdate = savedInstanceState.getLong(EXTRA_NEXT_UPDATE, 0);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mDayStart = 0;
mDayClause = "";
mFilterClause = new WhereClause("", null);
mDataUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
handler.post(new Runnable() {
public void run() {
updateDateSelection();
if(intent != null) {
mLoaderUpdate.startUpdate();
}
}
});
}
};
mDontWantToSeeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mLoaderUpdate.startUpdate();
}
};
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mDontWantToSeeReceiver, new IntentFilter(SettingConstants.DONT_WANT_TO_SEE_CHANGED));
mRefreshReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(mNextUpdate <= System.currentTimeMillis()) {
mLoaderUpdate.startUpdate();
}
else {
handler.post(new Runnable() {
@Override
public void run() {
if(!mIsLoading) {
mProgramListAdapter.notifyDataSetChanged();
}
}
});
}
}
};
IntentFilter intent = new IntentFilter(SettingConstants.DATA_UPDATE_DONE);
getActivity().registerReceiver(mDataUpdateReceiver, intent);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mRefreshReceiver, SettingConstants.RERESH_FILTER);
}
@Override
public void onDetach() {
if(mDataUpdateReceiver != null) {
getActivity().unregisterReceiver(mDataUpdateReceiver);
}
if(mRefreshReceiver != null) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mRefreshReceiver);
}
if(mDontWantToSeeReceiver != null) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mDontWantToSeeReceiver);
}
if(mMarkingsChangedReceiver != null) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mMarkingsChangedReceiver);
}
super.onDetach();
}
public void setDay(long dayStart) {
if(dayStart >= 0) {
mDayStart = dayStart;
mDayClause = " AND ( " + TvBrowserContentProvider.DATA_KEY_STARTTIME + ">=" + dayStart + " AND " + TvBrowserContentProvider.DATA_KEY_STARTTIME + "<" + (dayStart + (24 * 60 * 60000)) + " ) ";
}
else if(dayStart == DateSelection.VALUE_DATE_TODAY_TOMORROW) {
final Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DAY_OF_YEAR, 1);
tomorrow.set(Calendar.HOUR_OF_DAY, 23);
tomorrow.set(Calendar.MINUTE, 59);
tomorrow.set(Calendar.SECOND, 59);
tomorrow.set(Calendar.MILLISECOND, 999);
mDayStart = 0;
mDayClause = " AND ( " + TvBrowserContentProvider.DATA_KEY_ENDTIME + ">=" + System.currentTimeMillis() + " AND " + TvBrowserContentProvider.DATA_KEY_STARTTIME + "<" + tomorrow.getTimeInMillis() + " ) ";
}
else {
mDayClause = "";
mDayStart = 0;
}
mLoaderUpdate.startUpdate();
}
private boolean mIsShowingMarkings = false;
public void setMarkFilter(int pos) {
switch(pos) {
case 0: mFilterClause = new WhereClause("",null);break;
case 1: mFilterClause = new WhereClause(" AND ( " + TvBrowserContentProvider.DATA_KEY_MARKING_FAVORITE + " ) ",null);break;
case 2: {
WhereClause markings = ProgramUtils.getPluginMarkingsSelection(getActivity());
String where = markings.getWhere();
if(where.trim().isEmpty()) {
where = TvBrowserContentProvider.KEY_ID + "<0";
}
mFilterClause = new WhereClause(" AND ( " + where + " ) ", markings.getSelectionArgs());break;
}
case 3: mFilterClause = new WhereClause(" AND ( ( " + TvBrowserContentProvider.DATA_KEY_MARKING_REMINDER + " ) OR ( " + TvBrowserContentProvider.DATA_KEY_MARKING_FAVORITE_REMINDER + " ) ) ",null);break;
case 4: mFilterClause = new WhereClause(" AND ( " + TvBrowserContentProvider.DATA_KEY_MARKING_SYNC + " ) ",null);break;
case 5: mFilterClause = new WhereClause(" AND ( " + TvBrowserContentProvider.DATA_KEY_DONT_WANT_TO_SEE + " ) ",null);break;
}
mIsShowingMarkings = pos == 2;
mLoaderUpdate.startUpdate();
}
public void setScrollTime(long time) {
if(time == Integer.MAX_VALUE) {
time = -1 * System.currentTimeMillis();
}
mScrollTime = time;
}
public void scrollToTime() {
if(IOUtils.isDatabaseAccessible(getActivity())) {
handler.post(new Thread("SCROLL TO TIME THREAD") {
@Override
public void run() {
if(mScrollTime > 0) {
int testIndex = -1;
if(mScrollTime <= 1441) {
mScrollTime--;
if(mDayStart > 0) {
mScrollTime = mDayStart + mScrollTime * 60000;
}
else {
Calendar now = Calendar.getInstance();
now.set(Calendar.HOUR_OF_DAY,(int)(mScrollTime / 60));
now.set(Calendar.MINUTE,(int)(mScrollTime % 60));
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
mScrollTime = now.getTimeInMillis();
if(mScrollTime < System.currentTimeMillis()) {
mScrollTime += 1440 * 60000;
}
}
}
Cursor c = mProgramListAdapter.getCursor();
if(IOUtils.prepareAccessFirst(c)) {
try {
int index = c.getColumnIndex(TvBrowserContentProvider.DATA_KEY_STARTTIME);
int endIndex = c.getColumnIndex(TvBrowserContentProvider.DATA_KEY_ENDTIME);
int count = 0;
if(c != null && !c.isClosed()) {
do {
long startTime = c.getLong(index);
long endTime = c.getLong(endIndex);
if(startTime < mScrollTime && endTime > mScrollTime) {
testIndex = count++;
}
else if(startTime == mScrollTime) {
testIndex = count;
break;
}
else if(startTime > mScrollTime) {
if(testIndex == -1) {
testIndex = count;
}
break;
}
else {
count++;
}
}while(c.moveToNext());
}
}catch(IllegalStateException e) {}
}
mScrollTime = -1;
if(testIndex == -1) {
testIndex = 0;
}
final int scollIndex = testIndex;
handler.post(new Runnable() {
@Override
public void run() {
if(mListView != null) {
mListView.setSelection(scollIndex);
handler.post(new Runnable() {
@Override
public void run() {
mListView.setSelection(scollIndex);
}
});
}
}
});
}
else if(mScrollTime == 0 || mScrollTime < -1) {
Spinner test = (Spinner)((ViewGroup)getView().getParent()).findViewById(R.id.date_selection);
if(test != null && test.getSelectedItemPosition() > 0) {
test.setSelection(0);
}
else {
final AtomicInteger scrollIndex = new AtomicInteger(0);
if(mScrollTime < -1) {
final Cursor c = mProgramListAdapter.getCursor();
if(IOUtils.prepareAccessFirst(c)) {
do {
if(c.getLong(c.getColumnIndex(TvBrowserContentProvider.DATA_KEY_STARTTIME)) > System.currentTimeMillis()) {
scrollIndex.set(c.getPosition());
}
}while(scrollIndex.get() == 0 && c.moveToNext());
}
}
mScrollTime = -1;
handler.post(new Runnable() {
@Override
public void run() {
if(getView() != null) {
mListView.setSelection(scrollIndex.get());
}
}
});
}
}
}
});
}
}
public void setChannelID(long id) {
mChannelID = id;
mLoaderUpdate.startUpdate();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.program_list_fragment, container, false);
mListView = (ListView)view.findViewById(R.id.program_list_fragment_list_view);
initialize(view);
return view;
}
private void initialize(View rootView) {
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(getActivity());
IntentFilter channelUpdateFilter = new IntentFilter(SettingConstants.CHANNEL_UPDATE_DONE);
mDateSelection = (Spinner)rootView.findViewById(R.id.date_selection);
ArrayList<DateSelection> dateEntries = new ArrayList<DateSelection>();
mDateAdapter = new ArrayAdapter<DateSelection>(getActivity(), android.R.layout.simple_spinner_item, dateEntries);
mDateAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mDateSelection.setAdapter(mDateAdapter);
mDateSelection.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
DateSelection selection = mDateAdapter.getItem(pos);
setDay(selection.getTime());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
setDay(-1);
}
});
mChannelSelection = (Spinner)rootView.findViewById(R.id.channel_selection);
final Button minus = (Button)rootView.findViewById(R.id.channel_minus);
CompatUtils.setBackground(minus, ContextCompat.getDrawable(getActivity(),android.R.drawable.list_selector_background));
final Button plus = (Button)rootView.findViewById(R.id.channel_plus);
CompatUtils.setBackground(plus, ContextCompat.getDrawable(getActivity(),android.R.drawable.list_selector_background));
final ArrayList<ChannelSelection> channelEntries = new ArrayList<ChannelSelection>();
final ArrayAdapter<ChannelSelection> channelAdapter = new ArrayAdapter<ChannelSelection>(getActivity(), android.R.layout.simple_spinner_item, channelEntries) {
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent, android.R.layout.simple_spinner_dropdown_item);
}
private View getView(int position, View convertView, ViewGroup parent, int id) {
if(convertView == null) {
LayoutInflater inflater = getActivity().getLayoutInflater();
convertView = inflater.inflate(id, parent, false);
((TextView)convertView).setCompoundDrawablePadding(10);
((TextView)convertView).setGravity(Gravity.CENTER_VERTICAL);
}
int logoValue = Integer.parseInt(PrefUtils.getStringValue(R.string.CHANNEL_LOGO_NAME_PROGRAMS_LIST, R.string.channel_logo_name_programs_list_default));
boolean showOrderNumber = PrefUtils.getBooleanValue(R.string.SHOW_SORT_NUMBER_IN_PROGRAMS_LIST, R.bool.show_sort_number_in_programs_list_default);
ChannelSelection sel = getItem(position);
TextView text = (TextView)convertView;
if(sel.getID() == -1) {
text.setText(getResources().getString(R.string.all_channels));
text.setCompoundDrawables(null, null, null, null);
}
else {
if(logoValue == 0 || logoValue == 2 || sel.getLogo() == null) {
if(showOrderNumber) {
text.setText(sel.getOrderNumber() + sel.getName());
}
else {
text.setText(sel.getName());
}
}
else if(showOrderNumber) {
text.setText(sel.getOrderNumber());
}
else {
text.setText("");
}
if((logoValue == 0 || logoValue == 1) && sel.getLogo() != null) {
Drawable l = sel.getLogo();
text.setCompoundDrawables(l, null, null, null);
}
else {
text.setCompoundDrawables(null, null, null, null);
}
}
return convertView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent, android.R.layout.simple_spinner_item);
}
};
channelAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mChannelSelection.setAdapter(channelAdapter);
mChannelSelection.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
ChannelSelection selection = channelAdapter.getItem(pos);
setChannelID(selection.getID());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
setChannelID(-1);
}
});
View.OnClickListener onClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = mChannelSelection.getSelectedItemPosition();
if(v.equals(minus)) {
if(--pos < 0) {
pos = mChannelSelection.getCount()-1;
}
mChannelSelection.setSelection(pos);
}
else {
if(++pos >= mChannelSelection.getCount()) {
pos = 0;
}
mChannelSelection.setSelection(pos);
}
}
};
minus.setOnClickListener(onClick);
plus.setOnClickListener(onClick);
final Spinner filter = (Spinner)rootView.findViewById(R.id.program_selection);
ArrayList<String> filterEntries = new ArrayList<String>();
final ArrayAdapter<String> filterAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, filterEntries) {
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent, android.R.layout.simple_spinner_dropdown_item);
}
private View getView(int position, View convertView, ViewGroup parent, int id) {
if(convertView == null) {
LayoutInflater inflater = getActivity().getLayoutInflater();
convertView = inflater.inflate(id, parent, false);
((TextView)convertView).setGravity(Gravity.CENTER_VERTICAL);
}
String sel = getItem(position);
TextView text = (TextView)convertView;
text.setText(sel);
switch(position) {
case 0: CompatUtils.setBackground(convertView,ContextCompat.getDrawable(getContext(), android.R.drawable.list_selector_background));break;
case 1: convertView.setBackgroundColor(UiUtils.getColor(UiUtils.MARKED_FAVORITE_COLOR_KEY, getContext()));break;
case 2: convertView.setBackgroundColor(UiUtils.getColor(UiUtils.MARKED_COLOR_KEY, getContext()));break;
case 3: convertView.setBackgroundColor(UiUtils.getColor(UiUtils.MARKED_REMINDER_COLOR_KEY, getContext()));break;
case 4: convertView.setBackgroundColor(UiUtils.getColor(UiUtils.MARKED_SYNC_COLOR_KEY, getContext()));break;
case 5: CompatUtils.setBackground(convertView,ContextCompat.getDrawable(getContext(), android.R.drawable.list_selector_background));break;
}
return convertView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent, android.R.layout.simple_spinner_item);
}
};
filterAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
filter.setAdapter(filterAdapter);
filterAdapter.add(" " + getActivity().getString(R.string.all_programs));
filterAdapter.add(getResources().getString(R.string.title_favorites));
filterAdapter.add(getResources().getString(R.string.marking_value_marked));
filterAdapter.add(getResources().getString(R.string.marking_value_reminder));
filterAdapter.add(getResources().getString(R.string.marking_value_sync));
filterAdapter.add(" " + getResources().getString(R.string.action_dont_want_to_see));
filter.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
setMarkFilter(pos);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
setMarkFilter(-1);
}
});
mChannelUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(getActivity() != null && mLoaderUpdate.isRunning() && IOUtils.isDatabaseAccessible(context)) {
channelAdapter.clear();
channelAdapter.add(new ChannelSelection(-1, "0", getResources().getString(R.string.all_channels), null));
ContentResolver cr = getActivity().getContentResolver();
StringBuilder where = new StringBuilder(TvBrowserContentProvider.CHANNEL_KEY_SELECTION);
where.append(((TvBrowser)getActivity()).getFilterSelection(true).replace(TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID, TvBrowserContentProvider.KEY_ID));
Cursor channelCursor = cr.query(TvBrowserContentProvider.CONTENT_URI_CHANNELS, new String[] {TvBrowserContentProvider.KEY_ID,TvBrowserContentProvider.CHANNEL_KEY_NAME,TvBrowserContentProvider.CHANNEL_KEY_LOGO,TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER}, where.toString(), null, TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER + " , " + TvBrowserContentProvider.GROUP_KEY_GROUP_ID);
try {
if(channelCursor != null && channelCursor.moveToFirst()) {
do {
Bitmap logo = UiUtils.createBitmapFromByteArray(channelCursor.getBlob(channelCursor.getColumnIndex(TvBrowserContentProvider.CHANNEL_KEY_LOGO)));
Drawable logoDrawable = null;
if(logo != null) {
logoDrawable = SettingConstants.createLayerDrawable(22, getActivity(), logo);
}
String name = channelCursor.getString(channelCursor.getColumnIndex(TvBrowserContentProvider.CHANNEL_KEY_NAME));
String shortName = SettingConstants.SHORT_CHANNEL_NAMES.get(name);
if(shortName != null) {
name = shortName;
}
int id = channelCursor.getInt(channelCursor.getColumnIndex(TvBrowserContentProvider.KEY_ID));
ChannelSelection channelSel = new ChannelSelection(id, channelCursor.getString(channelCursor.getColumnIndex(TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER)) + ". ", name, logoDrawable);
channelAdapter.add(channelSel);
if(id == mChannelID) {
mChannelSelection.setSelection(channelAdapter.getCount()-1);
}
}while(channelCursor.moveToNext());
}
}finally {
IOUtils.close(channelCursor);
}
}
}
};
localBroadcastManager.registerReceiver(mChannelUpdateReceiver, channelUpdateFilter);
mLoaderUpdate.setIsRunning();
updateDateSelection();
mChannelUpdateReceiver.onReceive(null, null);
mLoaderUpdate.setIsNotRunning();
IntentFilter showChannelFilter = new IntentFilter(SettingConstants.SHOW_ALL_PROGRAMS_FOR_CHANNEL_INTENT);
BroadcastReceiver showChannel = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(getActivity() instanceof TvBrowser && mLoaderUpdate.isRunning()) {
int id = intent.getIntExtra(SettingConstants.CHANNEL_ID_EXTRA, -1);
long startTime = intent.getLongExtra(SettingConstants.EXTRA_START_TIME, -1);
long endTime = intent.getLongExtra(SettingConstants.EXTRA_END_TIME, -1);
int scrollIndex = intent.getIntExtra(SettingConstants.SCROLL_POSITION_EXTRA, -1);
int daySelection = intent.getIntExtra(SettingConstants.DAY_POSITION_EXTRA, -1);
int filterSelection = intent.getIntExtra(SettingConstants.FILTER_POSITION_EXTRA, -1);
boolean backstackup = !intent.getBooleanExtra(SettingConstants.NO_BACK_STACKUP_EXTRA, false);
ChannelSelection current = (ChannelSelection)mChannelSelection.getSelectedItem();
if(daySelection == -1 && endTime != -1 && startTime < System.currentTimeMillis() && endTime < System.currentTimeMillis() && startTime != endTime) {
if(mDateAdapter.getCount() > INDEX_DATE_TODAY) {
if(startTime < mDateAdapter.getItem(INDEX_DATE_TODAY).getTime()) {
daySelection = INDEX_DATE_YESTERDAY;
}
else {
daySelection = INDEX_DATE_TODAY;
}
}
}
if(current != null && filterSelection == -1 && backstackup) {
((TvBrowser)getActivity()).addProgramListState(mDateSelection.getSelectedItemPosition(), current.getID(), filter.getSelectedItemPosition(), getCurrentScrollIndex());
}
// setDontUpdate(true);
if(current == null || current.getID() != id) {
for(int i = 0; i < channelEntries.size(); i++) {
ChannelSelection sel = channelEntries.get(i);
if(sel.getID() == id) {
mChannelSelection.setSelection(i);
break;
}
}
}
if(filterSelection >= 0) {
filter.setSelection(filterSelection);
}
else {
filter.setSelection(0);
}
if(daySelection >= 0) {
if(daySelection < mDateSelection.getCount()) {
mDateSelection.setSelection(daySelection);
}
}
else {
mDateSelection.setSelection(1);
}
setScrollPos(scrollIndex);
setScrollTime(startTime);
// setDontUpdate(false);
mLoaderUpdate.startUpdate();
((TvBrowser)getActivity()).showProgramsListTab(backstackup);
}
}
};
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(showChannel, showChannelFilter);
}
private void updateDateSelection() {
if(getActivity() != null && mLoaderUpdate.isRunning() && mDateAdapter != null) {
mDateAdapter.clear();
mDateAdapter.add(new DateSelection(DateSelection.VALUE_DATE_TODAY_TOMORROW, getActivity()));
mDateAdapter.add(new DateSelection(DateSelection.VALUE_DATE_ALL, getActivity()));
long last = PrefUtils.getLongValueWithDefaultKey(R.string.META_DATA_DATE_LAST_KNOWN, R.integer.meta_data_date_known_default);
Calendar lastDay = Calendar.getInstance();
lastDay.setTimeInMillis(last);
lastDay.set(Calendar.HOUR_OF_DAY, 4);
lastDay.set(Calendar.MINUTE, 0);
lastDay.set(Calendar.SECOND, 0);
lastDay.set(Calendar.MILLISECOND, 0);
Calendar yesterday = Calendar.getInstance();
yesterday.set(Calendar.HOUR_OF_DAY, 4);
yesterday.set(Calendar.MINUTE, 0);
yesterday.set(Calendar.SECOND, 0);
yesterday.set(Calendar.MILLISECOND, 0);
yesterday.add(Calendar.DAY_OF_YEAR, -1);
long yesterdayStart = yesterday.getTimeInMillis();
long lastStart = lastDay.getTimeInMillis();
Calendar cal = Calendar.getInstance();
for(long day = yesterdayStart; day <= lastStart; day += (24 * 60 * 60000)) {
cal.setTimeInMillis(day);
cal.set(Calendar.HOUR_OF_DAY, 0);
mDateAdapter.add(new DateSelection(cal.getTimeInMillis(), getActivity()));
}
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
pref.registerOnSharedPreferenceChangeListener(this);
super.onActivityCreated(savedInstanceState);
mChannelID = NO_CHANNEL_SELECTION_ID;
// mDontUpdate = false;
mScrollPos = -1;
String[] projection = {
TvBrowserContentProvider.DATA_KEY_UNIX_DATE,
TvBrowserContentProvider.DATA_KEY_STARTTIME,
TvBrowserContentProvider.DATA_KEY_ENDTIME,
TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID,
TvBrowserContentProvider.DATA_KEY_TITLE,
TvBrowserContentProvider.DATA_KEY_EPISODE_TITLE,
TvBrowserContentProvider.DATA_KEY_GENRE,
TvBrowserContentProvider.DATA_KEY_PICTURE_COPYRIGHT,
TvBrowserContentProvider.DATA_KEY_CATEGORIES
};
mViewAndClickHandler = new ProgramListViewBinderAndClickHandler(getActivity(),this,handler);
// Create a new Adapter an bind it to the List View
mProgramListAdapter = new OrientationHandlingCursorAdapter(getActivity(),/*android.R.layout.simple_list_item_1*/R.layout.program_lists_entries,null,
projection,new int[] {R.id.startDateLabelPL,R.id.startTimeLabelPL,R.id.endTimeLabelPL,R.id.channelLabelPL,R.id.titleLabelPL,R.id.episodeLabelPL,R.id.genre_label_pl,R.id.picture_copyright_pl,R.id.info_label_pl},0,true,handler);
mProgramListAdapter.setViewBinder(mViewAndClickHandler);
mListView.setAdapter(mProgramListAdapter);
SeparatorDrawable drawable = new SeparatorDrawable(getActivity());
mListView.setDivider(drawable);
setDividerSize(PrefUtils.getStringValue(R.string.PREF_PROGRAM_LISTS_DIVIDER_SIZE, R.string.pref_program_lists_divider_size_default));
}
/*public void setDontUpdate(boolean value) {
mDontUpdate = value;
}*/
/*
private void startUpdateThread() {
startUpdateThread(0);
}
private void startUpdateThread(long nextUpdate) {
if(mKeepRunning && !mDontUpdate && nextUpdate <= System.currentTimeMillis()) {
if(getLoaderManager().hasRunningLoaders()) {
getLoaderManager().getLoader(0).cancelLoad();
}
mUpdateThread = new Thread("FragmentProgramsList Update Thread") {
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
if(mKeepRunning && !isRemoving() && !TvDataUpdateService.isRunning()) {
getLoaderManager().restartLoader(0, null, FragmentProgramsList.this);
}
}
});
}
};
mUpdateThread.start();
}
}*/
private static final String[] getProjection() {
String[] projection = null;
String[] infoCategories = TvBrowserContentProvider.INFO_CATEGORIES_COLUMNS_ARRAY;
if(PrefUtils.getBooleanValue(R.string.SHOW_PICTURE_IN_LISTS, R.bool.show_pictures_in_lists_default)) {
projection = new String[15 + TvBrowserContentProvider.MARKING_COLUMNS.length + infoCategories.length];
projection[projection.length-1] = TvBrowserContentProvider.DATA_KEY_PICTURE;
}
else {
projection = new String[14 + TvBrowserContentProvider.MARKING_COLUMNS.length + infoCategories.length];
}
projection[0] = TvBrowserContentProvider.KEY_ID;
projection[1] = TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID;
projection[2] = TvBrowserContentProvider.DATA_KEY_STARTTIME;
projection[3] = TvBrowserContentProvider.DATA_KEY_ENDTIME;
projection[4] = TvBrowserContentProvider.DATA_KEY_TITLE;
projection[5] = TvBrowserContentProvider.DATA_KEY_SHORT_DESCRIPTION;
projection[6] = TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER;
projection[7] = TvBrowserContentProvider.DATA_KEY_EPISODE_TITLE;
projection[8] = TvBrowserContentProvider.DATA_KEY_GENRE;
projection[9] = TvBrowserContentProvider.DATA_KEY_PICTURE_COPYRIGHT;
projection[10] = TvBrowserContentProvider.DATA_KEY_UNIX_DATE;
projection[11] = TvBrowserContentProvider.CHANNEL_KEY_NAME;
projection[12] = TvBrowserContentProvider.DATA_KEY_CATEGORIES;
projection[13] = TvBrowserContentProvider.CHANNEL_KEY_LOGO;
System.arraycopy(infoCategories, 0, projection, 14, infoCategories.length);
System.arraycopy(TvBrowserContentProvider.MARKING_COLUMNS, 0, projection, 14 + infoCategories.length, TvBrowserContentProvider.MARKING_COLUMNS.length);
return projection;
}
private String getWhereClause(boolean useCursorLoadLastTime) {
long time = (useCursorLoadLastTime && mCursorLoadLastTime != 0) ? mCursorLoadLastTime : System.currentTimeMillis();
String where = mDayStart == 0 ? " ( " + TvBrowserContentProvider.DATA_KEY_STARTTIME + "<=" + time + " AND " + TvBrowserContentProvider.DATA_KEY_ENDTIME + ">=" + time + " OR " + TvBrowserContentProvider.DATA_KEY_STARTTIME + ">" + time + " ) " : " ( " + TvBrowserContentProvider.DATA_KEY_STARTTIME + " > 0 ) ";
if(mChannelID != NO_CHANNEL_SELECTION_ID) {
where += "AND " + TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID + " IS " + mChannelID;
}
if(!mFilterClause.getWhere().contains(TvBrowserContentProvider.DATA_KEY_DONT_WANT_TO_SEE)) {
where += UiUtils.getDontWantToSeeFilterString(getActivity());
}
where += ((TvBrowser)getActivity()).getFilterSelection(false);
mCursorLoadLastTime = time;
return where;
}
private boolean mIsLoading;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
mIsLoading = true;
return new CursorLoader(getActivity(), TvBrowserContentProvider.CONTENT_URI_DATA_WITH_CHANNEL, getProjection(), getWhereClause(false) + mDayClause + mFilterClause.getWhere(), mFilterClause.getSelectionArgs(), TvBrowserContentProvider.DATA_KEY_STARTTIME + " , " + TvBrowserContentProvider.CHANNEL_KEY_ORDER_NUMBER + " , " + TvBrowserContentProvider.CHANNEL_KEY_CHANNEL_ID);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
mIsLoading = false;
mNextUpdate = 0;
mProgramListAdapter.swapCursor(c);
new Thread("FIND PROGRAMLIST NEXT UPDATE") {
@Override
public void run() {
if(IOUtils.isDatabaseAccessible(getActivity())) {
Cursor test = getActivity().getContentResolver().query(TvBrowserContentProvider.CONTENT_URI_DATA, new String[] {TvBrowserContentProvider.DATA_KEY_ENDTIME}, getWhereClause(true) + " AND " + TvBrowserContentProvider.DATA_KEY_ENDTIME +">0", null, TvBrowserContentProvider.DATA_KEY_ENDTIME + " ASC LIMIT 1");
try {
if(IOUtils.prepareAccessFirst(test)) {
mNextUpdate = test.getLong(test.getColumnIndex(TvBrowserContentProvider.DATA_KEY_ENDTIME));
}
}finally {
IOUtils.close(test);
}
}
}
}.start();
if(mScrollPos == -1) {
scrollToTime();
}
else {
if(mListView != null) {
mListView.setSelection(mScrollPos);
}
mScrollPos = -1;
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mIsLoading = false;
mProgramListAdapter.changeCursor(null);
}
private void setDividerSize(String size) {
mListView.setDividerHeight(UiUtils.convertDpToPixel(Integer.parseInt(size), getResources()));
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(getActivity() != null && !isDetached() && key != null) {
if(getString(R.string.PREF_PROGRAM_LISTS_DIVIDER_SIZE) != null && getString(R.string.PREF_PROGRAM_LISTS_DIVIDER_SIZE).equals(key)) {
setDividerSize(PrefUtils.getStringValue(R.string.PREF_PROGRAM_LISTS_DIVIDER_SIZE, R.string.pref_program_lists_divider_size_default));
}
else if(mListView != null && (getString(R.string.PREF_COLOR_SEPARATOR_LINE).equals(key) || getString(R.string.PREF_COLOR_SEPARATOR_SPACE).equals(key))) {
final Drawable separator = mListView.getDivider();
if(separator instanceof SeparatorDrawable) {
((SeparatorDrawable) separator).updateColors(getActivity());
}
}
}
}
public void setScrollPos(int pos) {
mScrollPos = pos;
}
public int getCurrentScrollIndex() {
int pos = mListView.getFirstVisiblePosition();
View view = mListView.getChildAt(0);
if(view != null && mProgramListAdapter.getCount() > 1 && view.getTop() < 0) {
pos++;
}
if(pos < 0) {
pos = 0;
}
return pos;
}
private static final class ChannelSelection {
private int mID;
private String mOrderNumber;
private String mName;
private Drawable mLogo;
public ChannelSelection(int ID, String orderNumber, String name, Drawable logo) {
mID = ID;
mOrderNumber = orderNumber;
mName = name;
mLogo = logo;
}
public int getID() {
return mID;
}
public String getOrderNumber() {
return mOrderNumber;
}
public String getName() {
return mName;
}
public Drawable getLogo() {
return mLogo;
}
@Override
public String toString() {
return mName;
}
}
public void updateChannels() {
if(mChannelUpdateReceiver != null && getActivity() != null && mLoaderUpdate.isRunning()) {
mChannelUpdateReceiver.onReceive(getActivity(), null);
}
}
@Override
public boolean showDate() {
String value = PrefUtils.getStringValue(R.string.SHOW_DATE_FOR_PROGRAMS_LIST, R.string.show_date_for_programs_list_default);
boolean returnValue = true;
switch(Integer.parseInt(value)) {
case 1: returnValue = (mDayStart == 0);break;
case 2: returnValue = false;break;
}
return returnValue;
}
@Override
public boolean showChannel() {
String value = PrefUtils.getStringValue(R.string.SHOW_CHANNEL_FOR_PROGRAMS_LIST, R.string.show_channel_for_programs_list_default);
boolean returnValue = true;
if(Integer.parseInt(value) == 1) {
returnValue = (mChannelID == NO_CHANNEL_SELECTION_ID);
}
return returnValue;
}
@Override
public void refreshMarkings() {
handler.post(new Runnable() {
@Override
public void run() {
if(!isDetached() && !mIsLoading && !isRemoving() && mLoaderUpdate.isRunning()) {
if(mIsShowingMarkings) {
setMarkFilter(2);
}
else {
mListView.invalidateViews();
}
}
}
});
}
}