C++程序  |  175行  |  4.38 KB

//
// Copyright 2005 The Android Open Source Project
//
// Our collection of devices.
//

// For compilers that support precompilation, include "wx/wx.h".
#include "wx/wxprec.h"

// Otherwise, include all standard headers
#ifndef WX_PRECOMP
# include "wx/wx.h"
#endif
//#include "wx/image.h"   // needed for Windows build


#include "PhoneCollection.h"
#include "PhoneData.h"
#include "MyApp.h"

#include "utils.h"

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <assert.h>

using namespace android;

/*static*/ PhoneCollection* PhoneCollection::mpInstance = NULL;

/*static*/ const char* PhoneCollection::kLayoutFile = "layout.xml";


/*
 * (Re-)scan the specified directory for phones.  We register a hit if we can
 * see a file called "<directory>/layout.xml".
 */
void PhoneCollection::ScanForPhones(const char* directory)
{
    /*
     * Scan through the directory and find everything that looks like it
     * might hold phone data.
     */
    StringArray strArr;

#ifdef BEFORE_ASSET
    DIR* dirp;
    struct dirent* entp;

    dirp = opendir(directory);
    if (dirp == NULL) {
        char buf[512];
        fprintf(stderr, "ERROR: unable to scan directory '%s' for phone data\n",
            directory);
        fprintf(stderr, "Current dir is %s\n", getcwd(buf, sizeof(buf)));
        return;
    }

    while (1) {
        wxString dirName;
        wxString fileName;

        entp = readdir(dirp);
        if (entp == NULL)
            break;              // done with scan
        dirName = directory;
        dirName += '/';
        dirName += entp->d_name;
        fileName = dirName;
        fileName += '/';
        fileName += kLayoutFile;

        if (access(fileName, R_OK) == 0) {
            strArr.push_back(dirName);
            //printf("--- examining '%s'\n", (const char*) fileName);
        }
    }
    closedir(dirp);
#else
    android::AssetManager* pAssetMgr = ((MyApp*)wxTheApp)->GetAssetManager();
    android::AssetDir* pDir;
    int i, count;

    pDir = pAssetMgr->openDir("");
    assert(pDir != NULL);
    count = pDir->getFileCount();

    for (i = 0; i < count; i++) {
        android::String8 layoutPath;

        if (pDir->getFileType(i) != kFileTypeDirectory)
            continue;

        layoutPath = pDir->getFileName(i);
        layoutPath.appendPath(kLayoutFile);

        if (pAssetMgr->getFileType(layoutPath.string()) == kFileTypeRegular) {
            strArr.push_back(pDir->getFileName(i).string());
            printf("--- examining '%s'\n", layoutPath.string());
        }
    }

    delete pDir;
#endif

    if (strArr.size() == 0) {
        fprintf(stderr, "ERROR: no phone data found in '%s'\n", directory);
        return;
    }

    /*
     * Found some candidates.  If they parse successfully, add them to
     * our list.
     *
     * We sort them first, because it's nice when everybody's user
     * interface looks the same.  Note we're sorting the directory name,
     * so it's possible to define a sort order in the filesystem that
     * doesn't require messing up the phone's title string.
     */
    mPhoneList.clear();
    strArr.sort(StringArray::cmpAscendingAlpha);

    for (int i = 0; i < strArr.size(); i++) {
        PhoneData tmpPhone;

        if (!tmpPhone.Create(strArr.getEntry(i))) {
            fprintf(stderr, "Sim: Abandoning phone '%s'\n", strArr.getEntry(i));
            //strArr.erase(i);
            //i--;
        } else {
            if (GetPhoneData(tmpPhone.GetName()) != NULL) {
                fprintf(stderr, "Sim: ERROR: duplicate name '%s' in '%s'\n",
                    tmpPhone.GetName(), strArr.getEntry(i));
            } else {
                mPhoneList.push_back(tmpPhone);
            }
        }
    }
}


/*
 * Return the Nth member of the phone data array.  (Replace w/Vector.)
 */
PhoneData* PhoneCollection::GetPhoneData(int idx)
{
    typedef List<PhoneData>::iterator Iter;

    for (Iter ii = mPhoneList.begin(); ii != mPhoneList.end(); ++ii) {
        if (idx == 0)
            return &(*ii);
        --idx;
    }
    return NULL;
}

/*
 * Return the entry whose phone data name matches "name".
 */
PhoneData* PhoneCollection::GetPhoneData(const char* name)
{
    typedef List<PhoneData>::iterator Iter;

    for (Iter ii = mPhoneList.begin(); ii != mPhoneList.end(); ++ii) {
        if (strcasecmp((*ii).GetName(), name) == 0)
            return &(*ii);
    }
    return NULL;
}