private void export(String defaultText) {
    if (cart.size() == 0) {
      showToast("Add items to your cart first!");
      return;
    }

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("Save as...");

    final EditText text = new EditText(this);
    text.setText(defaultText);
    builder.setView(text);

    builder.setPositiveButton(
        R.string.save,
        new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int which) {
            String filename = text.getText().toString();
            if (filename.equals("")) {
              showToast("Please enter a filename");
              export("");
              return;
            }

            if (filename.contains(" ") || filename.contains(".")) {
              showToast("Spaces and periods are not allowed");
              export(filename.replaceAll("[\\. ]", "_"));
              return;
            }

            // to ensure that all character dependencies are met
            List<LessonCharacter> dependencies = new ArrayList<LessonCharacter>();

            Collections.sort(cart);
            String xml = "<ttw name=\"" + filename + "\">\n";
            for (LessonItem item : cart) {
              if (item == allChars) {
                List<String> ids = Toolbox.dba.getAllCharIds();
                source = new ArrayList<LessonItem>(ids.size());
                for (String id : ids) {
                  LessonCharacter character = Toolbox.dba.getCharacterById(id);
                  if (!cart.contains(character) && !dependencies.contains(character)) {
                    dependencies.add(character);
                  }
                }
                continue;
              }

              xml += item.toXml();

              // if it's a lesson, we need to make sure dependencies are met
              if (item instanceof Lesson) {
                Lesson lesson = (Lesson) item;
                List<LessonItem> words = lesson.getWords();
                for (LessonItem word : words) {
                  List<LessonCharacter> characters = ((LessonWord) word).getCharacters();
                  for (LessonCharacter character : characters) {
                    if (!cart.contains(character) && !dependencies.contains(character)) {
                      dependencies.add(character);
                    }
                  }
                }
              }
            }

            // write out contents so far - all lessons
            writeStringToFile(xml, filename, /*append*/ false);
            xml = "";

            int counter = 1;
            for (LessonCharacter character : dependencies) {
              xml += character.toXml();

              // optimization:  write out contents after every 50 characters
              // to avoid out of memory crash that happens somewhere north of 500 characters
              if ((counter % 50) == 0) {
                writeStringToFile(xml, filename, /*append*/ true);
                xml = "";
              }
              counter++;
            }

            xml += "</ttw>\n";
            writeStringToFile(xml, filename, /*append*/ true);
          }
        });

    builder.setNegativeButton(
        R.string.cancel,
        new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int which) {
            showToast("Not saved");
          }
        });

    AlertDialog dialog = builder.create();

    Toolbox.showKeyboard(dialog);
    dialog.show();
  }
  /** Displays the filter popup and contains the code to filter */
  public void showFilterPopup() {

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("Apply Filter");

    final EditText filterText = new EditText(this);
    builder.setView(filterText);

    builder.setPositiveButton(
        R.string.apply,
        new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int which) {
            String search = filterText.getText().toString();
            if (search.equals("")) {
              hideKeyboard(filterText);
              return;
            }

            // Filter action: keep matching items from display list
            List<LessonItem> newList = new ArrayList<LessonItem>();
            switch (type) {
              case CHARACTER:
              case WORD:
                topLoop:
                for (LessonItem item : display) {
                  List<String> tags = item.getTags();
                  for (String tag : tags) {
                    if (Toolbox.containsMatch(2, tag, search)) {
                      newList.add(item);
                      continue topLoop;
                    }
                  }
                  Collection<String> values = item.getKeyValues().values();
                  for (String value : values) {
                    if (Toolbox.containsMatch(2, value, search)) {
                      newList.add(item);
                      continue topLoop;
                    }
                  }
                }
                break;
              case LESSON:
                for (LessonItem item : display) {
                  String name = ((Lesson) item).getLessonName();
                  if (Toolbox.containsMatch(2, name, search)) {
                    newList.add(item);
                  }
                }
                break;
            }
            display = newList;
            adapter = new ShoppingCartListAdapter(ShoppingCartActivity.this, display, vi);
            list.setAdapter(adapter);

            // Set state to filtered
            filterButton.setText(R.string.clear_filter);
            filtered = true;
            filterStatus.setText("Filter: " + search);
            hideKeyboard(filterText);
          }
        });
    builder.setNegativeButton(
        R.string.cancel,
        new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int which) {
            hideKeyboard(filterText);
          }
        });

    AlertDialog dialog = builder.create();

    Toolbox.showKeyboard(dialog);
    dialog.show();
  }