/android/import-contacts

To get this branch, use:
bzr branch http://bzr.ed.am/android/import-contacts

« back to all changes in this revision

Viewing changes to src/org/waxworlds/edam/importcontacts/FileChooser.java

  • Committer: edam
  • Date: 2009-01-13 06:35:26 UTC
  • Revision ID: edam@waxworlds.org-20090113063526-l9t1s9git4bav60a
- new contact's phone numebrs and email addresses are added to the caches after those contacts are updated to account for the situation where the same contact is imported again from another file (or the contact exists twice in the same file!?)

Show diffs side-by-side

added added

removed removed

1
 
/*
2
 
 * FileChooser.java
3
 
 *
4
 
 * Copyright (C) 2010 Tim Marston <edam@waxworlds.org>
5
 
 *
6
 
 * This file is part of the Import Contacts program (hereafter referred
7
 
 * to as "this program"). For more information, see
8
 
 * http://www.waxworlds.org/edam/software/android/import-contacts
9
 
 *
10
 
 * This program is free software: you can redistribute it and/or modify
11
 
 * it under the terms of the GNU General Public License as published by
12
 
 * the Free Software Foundation, either version 3 of the License, or
13
 
 * (at your option) any later version.
14
 
 *
15
 
 * This program is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 * GNU General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU General Public License
21
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 
 */
23
 
 
24
 
package org.waxworlds.edam.importcontacts;
25
 
 
26
 
import java.io.File;
27
 
import java.io.FileFilter;
28
 
import java.util.ArrayList;
29
 
 
30
 
import android.app.AlertDialog;
31
 
import android.app.Dialog;
32
 
import android.content.Context;
33
 
import android.content.DialogInterface;
34
 
import android.view.LayoutInflater;
35
 
import android.view.View;
36
 
import android.view.View.OnClickListener;
37
 
import android.view.ViewGroup;
38
 
import android.widget.AdapterView;
39
 
import android.widget.AdapterView.OnItemClickListener;
40
 
import android.widget.ArrayAdapter;
41
 
import android.widget.Button;
42
 
import android.widget.ImageView;
43
 
import android.widget.ListView;
44
 
import android.widget.TextView;
45
 
 
46
 
public class FileChooser
47
 
{
48
 
        // pick an existing directory
49
 
        public final static int MODE_DIR = 1;
50
 
 
51
 
        // pick an existing file
52
 
        public final static int MODE_FILE = 2;
53
 
 
54
 
 
55
 
        private Dialog _dialog;
56
 
 
57
 
        // mode
58
 
        private int _mode = MODE_DIR;
59
 
 
60
 
        // ok was pressed
61
 
        boolean _ok = false;
62
 
 
63
 
        // working path
64
 
        private String _path;
65
 
 
66
 
        // selected filename
67
 
        private String _filename;
68
 
 
69
 
        // enforce extension (in file-mode)
70
 
        private String[] _extensions;
71
 
 
72
 
        // path to secretly prefix all paths with
73
 
        private String _path_prefix = "";
74
 
 
75
 
        private Context _context;
76
 
        private ArrayList< RowItem > _items;
77
 
        private DialogInterface.OnDismissListener _on_dismiss_listener;
78
 
 
79
 
        // class that represents a row in the list
80
 
        private class RowItem
81
 
        {
82
 
                private String _name;
83
 
                private boolean _directory;
84
 
 
85
 
                public RowItem( String name, boolean directory )
86
 
                {
87
 
                        _name = name;
88
 
                        _directory = directory;
89
 
                }
90
 
 
91
 
                public String getName()
92
 
                {
93
 
                        return _name;
94
 
                }
95
 
 
96
 
                public boolean isDirectory()
97
 
                {
98
 
                        return _directory;
99
 
                }
100
 
        }
101
 
 
102
 
        // class to manage our list of RowItems
103
 
        private class RowItemAdapter extends ArrayAdapter< RowItem >
104
 
        {
105
 
                private ArrayList< RowItem > _items;
106
 
 
107
 
                public RowItemAdapter( Context context, int textview_resource_id,
108
 
                        ArrayList< RowItem > items )
109
 
                {
110
 
                        super( context, textview_resource_id, items );
111
 
                        _items = items;
112
 
                }
113
 
 
114
 
                @Override
115
 
                public View getView( int position, View convert_view, ViewGroup parent )
116
 
                {
117
 
                        View view = convert_view;
118
 
                        if( view == null ) {
119
 
                                LayoutInflater factory = LayoutInflater.from( _context );
120
 
                                view = factory.inflate(  R.layout.filechooser_row, null );
121
 
                        }
122
 
                        RowItem rowitem = _items.get( position );
123
 
                        if( rowitem != null ) {
124
 
                                ( (TextView)view.findViewById( R.id.name ) )
125
 
                                        .setText( rowitem.getName() );
126
 
                                ( (ImageView)view.findViewById( R.id.icon ) ).setVisibility(
127
 
                                        rowitem.isDirectory()? View.VISIBLE : View.GONE );
128
 
                        }
129
 
                        return view;
130
 
                }
131
 
        }
132
 
 
133
 
        class InvalidPathPrefixException extends RuntimeException
134
 
        {
135
 
        }
136
 
 
137
 
 
138
 
 
139
 
        // constructor
140
 
        public FileChooser( Context context )
141
 
        {
142
 
                _context = context;
143
 
        }
144
 
 
145
 
        public void setMode( int mode )
146
 
        {
147
 
                _mode = mode;
148
 
        }
149
 
 
150
 
        public void setPath( String path )
151
 
        {
152
 
                _path = cleanUpPath( path );
153
 
                File file = new File( _path_prefix + path.trim() );
154
 
 
155
 
                // path and filename
156
 
                if( file.isFile() ) {
157
 
                        _path = _path.substring( 0, _path.length() - 1 );
158
 
                        _filename = _path.substring( _path.lastIndexOf( '/' ) + 1 );
159
 
                        _path = _path.substring( 0, _path.length() - _filename.length() );
160
 
                }
161
 
 
162
 
                // else, treat as just a path
163
 
                else
164
 
                        _filename = "";
165
 
        }
166
 
 
167
 
        public void setExtensions( String[] extensions )
168
 
        {
169
 
                _extensions = extensions;
170
 
        }
171
 
 
172
 
        // set dismiss listener
173
 
        public void setDismissListener(
174
 
                DialogInterface.OnDismissListener on_dismiss_listener )
175
 
        {
176
 
                _on_dismiss_listener = on_dismiss_listener;
177
 
        }
178
 
 
179
 
        // set the path prefix
180
 
        public void setPathPrefix( String path_prefix )
181
 
        {
182
 
                // set to cleaned-up path, with trailaing '/' removed so that it can be
183
 
                // trivially pre-pended to a cleaned-up path
184
 
                _path_prefix = cleanUpPath( path_prefix );
185
 
                _path_prefix = _path_prefix.substring( 0, _path_prefix.length() - 1 );
186
 
        }
187
 
 
188
 
        public boolean getOk()
189
 
        {
190
 
                return _ok;
191
 
        }
192
 
 
193
 
        public String getPath()
194
 
        {
195
 
                return _path + _filename;
196
 
        }
197
 
 
198
 
        public Dialog onCreateDialog()
199
 
        {
200
 
                // custom layout in an AlertDialog
201
 
                LayoutInflater factory = LayoutInflater.from( _context );
202
 
                final View dialogView = factory.inflate(
203
 
                        R.layout.filechooser, null );
204
 
 
205
 
                // wire up buttons
206
 
                ( (Button)dialogView.findViewById( R.id.ok ) )
207
 
                        .setOnClickListener( _fileChooserButtonListener );
208
 
                ( (ListView)dialogView.findViewById( R.id.list ) )
209
 
                        .setOnItemClickListener( _fileChooserItemClickListener );
210
 
 
211
 
                // return dialog
212
 
                Dialog dialog = new AlertDialog.Builder( _context )
213
 
                        .setTitle( " " )
214
 
                        .setView( dialogView )
215
 
                        .create();
216
 
                dialog.setOnDismissListener( _on_dismiss_listener );
217
 
                return dialog;
218
 
        }
219
 
 
220
 
        private OnClickListener _fileChooserButtonListener = new OnClickListener() {
221
 
                public void onClick( View view )
222
 
                {
223
 
                        switch( view.getId() )
224
 
                        {
225
 
                        case R.id.ok:
226
 
                                // close dialog and free (don't keep a reference)
227
 
                                _ok = true;
228
 
                                _dialog.dismiss();
229
 
                                break;
230
 
                        }
231
 
                }
232
 
        };
233
 
 
234
 
        private OnItemClickListener _fileChooserItemClickListener = new OnItemClickListener() {
235
 
                public void onItemClick( AdapterView adapterView, View view, int position, long id )
236
 
                {
237
 
                        RowItem rowitem = _items.get( position );
238
 
 
239
 
                        // handle directory changes
240
 
                        if( rowitem.isDirectory() )
241
 
                        {
242
 
                                String dirname = rowitem.getName();
243
 
                                if( dirname.equals( ".." ) )
244
 
                                        strtipLastFilepartFromPath();
245
 
                                else
246
 
                                        _path += dirname + "/";
247
 
                                _filename = "";
248
 
 
249
 
                                updateList();
250
 
                        }
251
 
 
252
 
                        // handle file selections
253
 
                        else
254
 
                        {
255
 
                                _filename = rowitem.getName();
256
 
                                updateCurrentSelection();
257
 
                        }
258
 
                }
259
 
        };
260
 
 
261
 
        public void onPrepareDialog( Context context, Dialog dialog )
262
 
        {
263
 
                // set up reference to dialog
264
 
                _dialog = dialog;
265
 
                _context = context;
266
 
 
267
 
                // reset "ok"
268
 
                _ok = false;
269
 
 
270
 
                // pick text based on mode
271
 
                int title = 0, current = 0;
272
 
                switch( _mode ) {
273
 
                case MODE_DIR:
274
 
                        title = R.string.filechooser_title_dir;
275
 
                        current = R.string.filechooser_current_dir;
276
 
                        break;
277
 
                case MODE_FILE:
278
 
                        title = R.string.filechooser_title_file;
279
 
                        current = R.string.filechooser_current_file;
280
 
                        break;
281
 
                }
282
 
                dialog.setTitle( title );
283
 
                ( (TextView)dialog.findViewById( R.id.current ) )
284
 
                        .setText( _context.getString(  current ) );
285
 
 
286
 
                // clear filename in directory mode
287
 
                if( _mode == MODE_DIR )
288
 
                        _filename = "";
289
 
 
290
 
                // set root path icon
291
 
                ( (ImageView)_dialog.findViewById( R.id.icon ) )
292
 
                        .setImageResource( pathIcon( cleanUpPath( _path_prefix ) ) );
293
 
 
294
 
                // setup current-path-specific stuff
295
 
                updateList();
296
 
        }
297
 
 
298
 
        public static String cleanUpPath( String path )
299
 
        {
300
 
                path = path.trim();
301
 
 
302
 
                // ensure it starts and ends in a '/'
303
 
                if( !path.startsWith( "/" ) ) path = "/" + path;
304
 
                if( !path.endsWith( "/" ) ) path += "/";
305
 
 
306
 
                return path;
307
 
        }
308
 
 
309
 
        public static int pathIcon( String path )
310
 
        {
311
 
                if( path.equals( "/sdcard/" ) )
312
 
                        return R.drawable.sdcard;
313
 
 
314
 
                return R.drawable.directory;
315
 
        }
316
 
 
317
 
        public String prettyPrint( String full_path, boolean return_full )
318
 
        {
319
 
                String path = full_path;
320
 
 
321
 
                // special names
322
 
                if( path.equals( "/sdcard/" ) )
323
 
                        return " " + _context.getString( R.string.filechooser_path_sdcard );
324
 
 
325
 
                // remove prefix, if present
326
 
                if( path.startsWith( _path_prefix + "/" ) )
327
 
                        path = path.substring( _path_prefix.length() );
328
 
 
329
 
                // unless path is "/", strip trailing "/".
330
 
                if( path.length() > 1 && path.endsWith( "/" ) )
331
 
                        path = path.substring( 0, path.length() - 1 );
332
 
 
333
 
                // if full path not required, strip off preceding directories
334
 
                if( !return_full ) {
335
 
                        int idx = path.lastIndexOf( "/" );
336
 
                        if( idx != -1 ) path = path.substring( idx + 1 );
337
 
                }
338
 
 
339
 
                return path;
340
 
        }
341
 
 
342
 
        protected void strtipLastFilepartFromPath()
343
 
        {
344
 
                int at = _path.lastIndexOf( '/', _path.length() - 2 );
345
 
                if( at != -1 ) _path = _path.substring( 0, at + 1 );
346
 
        }
347
 
 
348
 
        protected void updateList()
349
 
        {
350
 
                // reset item list
351
 
                _items = new ArrayList< RowItem >();
352
 
 
353
 
                // open directory (and ensure _path is a directory)
354
 
                File dir = new File( _path_prefix + _path );
355
 
                while( !dir.isDirectory() ) {
356
 
                        if( _path == "/" )
357
 
                                throw new InvalidPathPrefixException();
358
 
                        strtipLastFilepartFromPath();
359
 
                        dir = new File( _path_prefix + _path );
360
 
                }
361
 
 
362
 
                // add ".."?
363
 
                if( !_path.equals( "/" ) )
364
 
                        _items.add( new RowItem( "..", true ) );
365
 
 
366
 
                // get directories
367
 
                class DirFilter implements FileFilter {
368
 
                        public boolean accept( File file ) {
369
 
                                return file.isDirectory() && file.getName().charAt( 0 ) != '.';
370
 
                        }
371
 
                }
372
 
                File[] files = dir.listFiles( new DirFilter() );
373
 
                for( int i = 0; i < files.length; i++ )
374
 
                        _items.add( new RowItem( files[ i ].getName(), true ) );
375
 
 
376
 
                // get files
377
 
                if( _mode == MODE_FILE )
378
 
                {
379
 
                        class VCardFilter implements FileFilter {
380
 
                                public boolean accept( File file ) {
381
 
                                        if( file.isDirectory() || file.getName().startsWith( "." ) )
382
 
                                                return false;
383
 
                                        String filename = file.getName().toLowerCase();
384
 
                                        for( int i = 0; i < _extensions.length; i++ )
385
 
                                                if( filename.endsWith( "." + _extensions[ i ] ) )
386
 
                                                        return true;
387
 
                                        return false;
388
 
                                }
389
 
                        }
390
 
                        files = dir.listFiles( new VCardFilter() );
391
 
                        for( int i = 0; i < files.length; i++ )
392
 
                                _items.add( new RowItem( files[ i ].getName(), false ) );
393
 
                }
394
 
 
395
 
                // setup directory list
396
 
                ( (ListView)_dialog.findViewById( R.id.list ) ).setAdapter(
397
 
                        new RowItemAdapter( _context, R.layout.filechooser_row,
398
 
                                _items ) );
399
 
 
400
 
                updateCurrentSelection();
401
 
        }
402
 
 
403
 
        private void updateCurrentSelection()
404
 
        {
405
 
                // set current path
406
 
                ( (TextView)_dialog.findViewById( R.id.path ) ).setText(
407
 
                        prettyPrint( _path_prefix + _path + _filename, true ) );
408
 
 
409
 
                // enable/disable ok button
410
 
                if( _mode == MODE_FILE )
411
 
                        _dialog.findViewById( R.id.ok ).setEnabled( _filename != "" );
412
 
                else
413
 
                        _dialog.findViewById( R.id.ok ).setEnabled( true );
414
 
        }
415
 
 
416
 
}