OSDN Git Service

auto import from //depot/cupcake/@135843
[android-x86/packages-apps-Calendar.git] / src / com / android / calendar / IcsImportActivity.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.calendar;
18
19 import android.app.Activity;
20 import android.content.ContentResolver;
21 import android.content.ContentValues;
22 import android.content.Intent;
23 import android.database.Cursor;
24 import android.net.Uri;
25 import android.os.Bundle;
26 import android.pim.ICalendar;
27 import android.provider.Calendar;
28 import android.util.Config;
29 import android.util.Log;
30 import android.view.View;
31 import android.widget.ArrayAdapter;
32 import android.widget.Button;
33 import android.widget.ImageView;
34 import android.widget.Spinner;
35 import android.widget.TextView;
36
37 import java.io.ByteArrayOutputStream;
38 import java.io.FileNotFoundException;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.util.ArrayList;
42
43 public class IcsImportActivity extends Activity {
44
45     private static final String TAG = "Calendar";
46
47     // TODO: consolidate this code with the EventActivity
48     private static class CalendarInfo {
49         public final long id;
50         public final String name;
51
52         public CalendarInfo(long id, String name) {
53             this.id = id;
54             this.name = name;
55         }
56
57         @Override
58         public String toString() {
59             return name;
60         }
61     }
62
63     private View mView;
64     private Button mImportButton;
65     private Button mCancelButton;
66     private Spinner mCalendars;
67     private ImageView mCalendarIcon;
68     private TextView mNumEvents;
69
70     private ICalendar.Component mCalendar = null;
71
72     private View.OnClickListener mImportListener = new View.OnClickListener() {
73         public void onClick(View v) {
74             importCalendar();
75             finish();
76         }
77     };
78
79     private View.OnClickListener mCancelListener = new View.OnClickListener() {
80         public void onClick(View v) {
81             finish();
82         }
83     };
84
85     @Override
86     protected void onCreate(Bundle icicle) {
87         super.onCreate(icicle);
88         setContentView(R.layout.ics_import_activity);
89         mView = findViewById(R.id.import_ics);
90
91         mCalendarIcon = (ImageView) findViewById(R.id.calendar_icon);
92         mCalendars = (Spinner) findViewById(R.id.calendars);
93         populateCalendars();
94
95         mImportButton = (Button) findViewById(R.id.import_button);
96         mImportButton.setOnClickListener(mImportListener);
97         mCancelButton = (Button) findViewById(R.id.cancel_button);
98         mCancelButton.setOnClickListener(mCancelListener);
99
100         mNumEvents = (TextView) findViewById(R.id.num_events);
101
102         Intent intent = getIntent();
103         String data = intent.getStringExtra("ics");
104         if (data == null) {
105             Uri content = intent.getData();
106             if (content != null) {
107                 InputStream is = null;
108                 try {
109                     is = getContentResolver().openInputStream(content);
110                     ByteArrayOutputStream baos = new ByteArrayOutputStream();
111                     byte[] buf = new byte[8096];
112                     int bytesRead = -1;
113                     int pos = 0;
114                     while ((bytesRead = is.read(buf)) != -1) {
115                         baos.write(buf, pos, bytesRead);
116                         pos += bytesRead;
117                     }
118                     data = new String(baos.toByteArray(), "UTF-8");
119                 } catch (FileNotFoundException fnfe) {
120                     Log.w(TAG, "Could not open data.", fnfe);
121                 } catch (IOException ioe) {
122                     Log.w(TAG, "Could not read data.", ioe);
123                 } finally {
124                     if (is != null) {
125                         try {
126                             is.close();
127                         } catch (IOException ioe) {
128                             Log.w(TAG, "Could not close InputStream.", ioe);
129                         }
130                     }
131                 }
132             }
133         }
134         if (data == null) {
135             Log.w(TAG, "No iCalendar data to parse.");
136             finish();
137             return;
138         }
139         parseCalendar(data);
140     }
141
142     private void populateCalendars() {
143         ContentResolver cr = getContentResolver();
144         Cursor c = cr.query(Calendar.Calendars.CONTENT_URI,
145                       new String[] { Calendar.Calendars._ID,
146                                      Calendar.Calendars.DISPLAY_NAME,
147                                      Calendar.Calendars.SELECTED,
148                                      Calendar.Calendars.ACCESS_LEVEL },
149                       Calendar.Calendars.SELECTED + "=1 AND "
150                           + Calendar.Calendars.ACCESS_LEVEL + ">="
151                           + Calendar.Calendars.CONTRIBUTOR_ACCESS,
152                       null, null /* sort order */);
153
154         ArrayList<CalendarInfo> items = new ArrayList<CalendarInfo>();
155         try {
156             // TODO: write a custom adapter that wraps the cursor?
157             int idColumn = c.getColumnIndex(Calendar.Calendars._ID);
158             int nameColumn = c.getColumnIndex(Calendar.Calendars.DISPLAY_NAME);
159             while (c.moveToNext()) {
160                 long id = c.getLong(idColumn);
161                 String name = c.getString(nameColumn);
162                 items.add(new CalendarInfo(id, name));
163             }
164         } finally {
165             c.deactivate();
166         }
167
168         mCalendars.setAdapter(new ArrayAdapter<CalendarInfo>(this,
169                 android.R.layout.simple_spinner_item, items));
170     }
171
172     private void parseCalendar(String data) {
173         mCalendar = null;
174         try {
175             mCalendar = ICalendar.parseCalendar(data);
176         } catch (ICalendar.FormatException fe) {
177             if (Config.LOGD) {
178                 Log.d(TAG, "Could not parse iCalendar.", fe);
179                 // TODO: show an error message.
180                 finish();
181                 return;
182             }
183         }
184         if (mCalendar.getComponents() == null) {
185             Log.d(TAG, "No events in iCalendar.");
186             finish();
187             return;
188         }
189         int numEvents = 0;
190         for (ICalendar.Component component : mCalendar.getComponents()) {
191             if ("VEVENT".equals(component.getName())) {
192                 // TODO: display a list of the events (start time, title) in
193                 // the UI?
194                 ++numEvents;
195             }
196         }
197         // TODO: special-case a single-event calendar.  switch to the
198         // EventActivity, once the EventActivity supports displaying data that
199         // is passed in via the extras.
200         // OR, we could flip things around, where the EventActivity handles ICS
201         // import by default, and delegates to the IcsImportActivity if it finds
202         // that there are more than one event in the iCalendar.  that would
203         // avoid an extra activity launch for the expected common case of
204         // importing a single event.
205         mNumEvents.setText(Integer.toString(numEvents));
206     }
207
208     private void importCalendar() {
209
210         ContentResolver cr = getContentResolver();
211
212         int numImported = 0;
213         ContentValues values = new ContentValues();
214
215         for (ICalendar.Component component : mCalendar.getComponents()) {
216             if ("VEVENT".equals(component.getName())) {
217                 CalendarInfo calInfo =
218                         (CalendarInfo) mCalendars.getSelectedItem();
219                 if (Calendar.Events.insertVEvent(cr, component, calInfo.id,
220                         Calendar.Events.STATUS_CONFIRMED, values) != null) {
221                     ++numImported;
222                 }
223             }
224         }
225         // TODO: display how many were imported.
226     }
227 }