/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/export-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()
141
 
        {
142
 
        }
143
 
 
144
 
        public void setMode( int mode )
145
 
        {
146
 
                _mode = mode;
147
 
        }
148
 
 
149
 
        public void setPath( String path )
150
 
        {
151
 
                _path = cleanUpPath( path );
152
 
                File file = new File( _path_prefix + path.trim() );
153
 
 
154
 
                // path and filename
155
 
                if( file.isFile() ) {
156
 
                        _path = _path.substring( 0, _path.length() - 1 );
157
 
                        _filename = _path.substring( _path.lastIndexOf( '/' ) + 1 );
158
 
                        _path = _path.substring( 0, _path.length() - _filename.length() );
159
 
                }
160
 
 
161
 
                // else, treat as just a path
162
 
                else
163
 
                        _filename = "";
164
 
        }
165
 
 
166
 
        public void setExtensions( String[] extensions )
167
 
        {
168
 
                _extensions = extensions;
169
 
        }
170
 
 
171
 
        // set dismiss listener
172
 
        public void setDismissListener(
173
 
                DialogInterface.OnDismissListener on_dismiss_listener )
174
 
        {
175
 
                _on_dismiss_listener = on_dismiss_listener;
176
 
        }
177
 
 
178
 
        // set the path prefix
179
 
        public void setPathPrefix( String path_prefix )
180
 
        {
181
 
                // set to cleaned-up path, with trailaing '/' removed so that it can be
182
 
                // trivially pre-pended to a cleaned-up path
183
 
                _path_prefix = cleanUpPath( path_prefix );
184
 
                _path_prefix = _path_prefix.substring( 0, _path_prefix.length() - 1 );
185
 
        }
186
 
 
187
 
        public boolean getOk()
188
 
        {
189
 
                return _ok;
190
 
        }
191
 
 
192
 
        public String getPath()
193
 
        {
194
 
                return _path + _filename;
195
 
        }
196
 
 
197
 
        public Dialog onCreateDialog( Context context )
198
 
        {
199
 
                _context = context;
200
 
 
201
 
                // custom layout in an AlertDialog
202
 
                LayoutInflater factory = LayoutInflater.from( context );
203
 
                final View dialogView = factory.inflate(
204
 
                        R.layout.filechooser, null );
205
 
 
206
 
                // wire up buttons
207
 
                ( (Button)dialogView.findViewById( R.id.ok ) )
208
 
                        .setOnClickListener( _fileChooserButtonListener );
209
 
                ( (ListView)dialogView.findViewById( R.id.list ) )
210
 
                        .setOnItemClickListener( _fileChooserItemClickListener );
211
 
 
212
 
                // return dialog
213
 
                Dialog dialog = new AlertDialog.Builder( context )
214
 
                        .setTitle( " " )
215
 
                        .setView( dialogView )
216
 
                        .create();
217
 
                dialog.setOnDismissListener( _on_dismiss_listener );
218
 
                return dialog;
219
 
        }
220
 
 
221
 
        private OnClickListener _fileChooserButtonListener = new OnClickListener() {
222
 
                public void onClick( View view )
223
 
                {
224
 
                        switch( view.getId() )
225
 
                        {
226
 
                        case R.id.ok:
227
 
                                // close dialog and free (don't keep a reference)
228
 
                                _ok = true;
229
 
                                _dialog.dismiss();
230
 
                                break;
231
 
                        }
232
 
                }
233
 
        };
234
 
 
235
 
        private OnItemClickListener _fileChooserItemClickListener = new OnItemClickListener() {
236
 
                public void onItemClick( AdapterView adapterView, View view, int position, long id )
237
 
                {
238
 
                        RowItem rowitem = _items.get( position );
239
 
 
240
 
                        // handle directory changes
241
 
                        if( rowitem.isDirectory() )
242
 
                        {
243
 
                                String dirname = rowitem.getName();
244
 
                                if( dirname.equals( ".." ) )
245
 
                                        strtipLastFilepartFromPath();
246
 
                                else
247
 
                                        _path += dirname + "/";
248
 
                                _filename = "";
249
 
 
250
 
                                updateList();
251
 
                        }
252
 
 
253
 
                        // handle file selections
254
 
                        else
255
 
                        {
256
 
                                _filename = rowitem.getName();
257
 
                                updateCurrentSelection();
258
 
                        }
259
 
                }
260
 
        };
261
 
 
262
 
        public void onPrepareDialog( Context context, Dialog dialog )
263
 
        {
264
 
                // set up reference to dialog
265
 
                _dialog = dialog;
266
 
                _context = context;
267
 
 
268
 
                // reset "ok"
269
 
                _ok = false;
270
 
 
271
 
                // pick text based on mode
272
 
                int title = 0, current = 0;
273
 
                switch( _mode ) {
274
 
                case MODE_DIR:
275
 
                        title = R.string.filechooser_title_dir;
276
 
                        current = R.string.filechooser_current_dir;
277
 
                        break;
278
 
                case MODE_FILE:
279
 
                        title = R.string.filechooser_title_file;
280
 
                        current = R.string.filechooser_current_file;
281
 
                        break;
282
 
                }
283
 
                dialog.setTitle( title );
284
 
                ( (TextView)dialog.findViewById( R.id.current ) )
285
 
                        .setText( _context.getString(  current ) );
286
 
 
287
 
                // clear filename in directory mode
288
 
                if( _mode == MODE_DIR )
289
 
                        _filename = "";
290
 
 
291
 
                // set root path icon
292
 
                ( (ImageView)_dialog.findViewById( R.id.icon ) )
293
 
                        .setImageResource( pathIcon( cleanUpPath( _path_prefix ) ) );
294
 
 
295
 
                // setup current-path-specific stuff
296
 
                updateList();
297
 
        }
298
 
 
299
 
        public static String cleanUpPath( String path )
300
 
        {
301
 
                path = path.trim();
302
 
 
303
 
                // ensure it starts and ends in a '/'
304
 
                if( !path.startsWith( "/" ) ) path = "/" + path;
305
 
                if( !path.endsWith( "/" ) ) path += "/";
306
 
 
307
 
                return path;
308
 
        }
309
 
 
310
 
        public static int pathIcon( String path )
311
 
        {
312
 
                if( path.equals( "/sdcard/" ) )
313
 
                        return R.drawable.sdcard;
314
 
 
315
 
                return R.drawable.directory;
316
 
        }
317
 
 
318
 
        public String prettyPrint( String full_path, boolean return_full )
319
 
        {
320
 
                String path = full_path;
321
 
 
322
 
                // special names
323
 
                if( path.equals( "/sdcard/" ) )
324
 
                        return " " + _context.getString( R.string.filechooser_path_sdcard );
325
 
 
326
 
                // remove prefix, if present
327
 
                if( path.startsWith( _path_prefix + "/" ) )
328
 
                        path = path.substring( _path_prefix.length() );
329
 
 
330
 
                // unless path is "/", strip trailing "/".
331
 
                if( path.length() > 1 && path.endsWith( "/" ) )
332
 
                        path = path.substring( 0, path.length() - 1 );
333
 
 
334
 
                // if full path not required, strip off preceding directories
335
 
                if( !return_full ) {
336
 
                        int idx = path.lastIndexOf( "/" );
337
 
                        if( idx != -1 ) path = path.substring( idx + 1 );
338
 
                }
339
 
 
340
 
                return path;
341
 
        }
342
 
 
343
 
        protected void strtipLastFilepartFromPath()
344
 
        {
345
 
                int at = _path.lastIndexOf( '/', _path.length() - 2 );
346
 
                if( at != -1 ) _path = _path.substring( 0, at + 1 );
347
 
        }
348
 
 
349
 
        protected void updateList()
350
 
        {
351
 
                // reset item list
352
 
                _items = new ArrayList< RowItem >();
353
 
 
354
 
                // open directory (and ensure _path is a directory)
355
 
                File dir = new File( _path_prefix + _path );
356
 
                while( !dir.isDirectory() ) {
357
 
                        if( _path == "/" )
358
 
                                throw new InvalidPathPrefixException();
359
 
                        strtipLastFilepartFromPath();
360
 
                        dir = new File( _path_prefix + _path );
361
 
                }
362
 
 
363
 
                // add ".."?
364
 
                if( !_path.equals( "/" ) )
365
 
                        _items.add( new RowItem( "..", true ) );
366
 
 
367
 
                // get directories
368
 
                class DirFilter implements FileFilter {
369
 
                        public boolean accept( File file ) {
370
 
                                return file.isDirectory() && file.getName().charAt( 0 ) != '.';
371
 
                        }
372
 
                }
373
 
                File[] files = dir.listFiles( new DirFilter() );
374
 
                for( int i = 0; i < files.length; i++ )
375
 
                        _items.add( new RowItem( files[ i ].getName(), true ) );
376
 
 
377
 
                // get files
378
 
                if( _mode == MODE_FILE )
379
 
                {
380
 
                        class VCardFilter implements FileFilter {
381
 
                                public boolean accept( File file ) {
382
 
                                        if( file.isDirectory() || file.getName().startsWith( "." ) )
383
 
                                                return false;
384
 
                                        String filename = file.getName().toLowerCase();
385
 
                                        for( int i = 0; i < _extensions.length; i++ )
386
 
                                                if( filename.endsWith( "." + _extensions[ i ] ) )
387
 
                                                        return true;
388
 
                                        return false;
389
 
                                }
390
 
                        }
391
 
                        files = dir.listFiles( new VCardFilter() );
392
 
                        for( int i = 0; i < files.length; i++ )
393
 
                                _items.add( new RowItem( files[ i ].getName(), false ) );
394
 
                }
395
 
 
396
 
                // setup directory list
397
 
                ( (ListView)_dialog.findViewById( R.id.list ) ).setAdapter(
398
 
                        new RowItemAdapter( _context, R.layout.filechooser_row,
399
 
                                _items ) );
400
 
 
401
 
                updateCurrentSelection();
402
 
        }
403
 
 
404
 
        private void updateCurrentSelection()
405
 
        {
406
 
                // set current path
407
 
                ( (TextView)_dialog.findViewById( R.id.path ) ).setText(
408
 
                        prettyPrint( _path_prefix + _path + _filename, true ) );
409
 
 
410
 
                // enable/disable ok button
411
 
                if( _mode == MODE_FILE )
412
 
                        _dialog.findViewById( R.id.ok ).setEnabled( _filename != "" );
413
 
        }
414
 
 
415
 
}