Index: potx.css
===================================================================
RCS file: potx.css
diff -N potx.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ potx.css	27 Dec 2009 14:40:39 -0000
@@ -0,0 +1,41 @@
+/* $Id$ */
+
+#potx-export-picker {
+  margin-bottom: 2em;
+}
+
+#potx-export-picker .potx-project {
+  border: 2px solid #cdcdcd;
+  margin-top: 1em;
+  clear: both;
+}
+#potx-export-picker .potx-project-name {
+  font-weight: bold;
+  font-size: 1.3em;
+  padding: 0.3em;
+  background-color: #cdcdcd;
+}
+#potx-export-picker .potx-project-name .potx-description {
+  font-weight: normal;
+  vertical-align: baseline;
+  font-size: 0.6em;
+  float: right;
+}
+#potx-export-picker .form-item {
+  margin: 0;
+}
+#potx-export-picker .form-item label.option {
+  display: block;
+  font-weight: inherit;
+}
+#potx-export-picker .potx-subprojects {
+  padding: 0.2em;
+}
+#potx-export-picker .potx-subprojects .form-item {
+  float: left;
+  width: 30%;
+  padding: 0.1em 0.3em;
+}
+#potx-export-picker .potx-subprojects .form-item:hover {
+  background-color: #ededed;
+}
Index: potx.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/potx/Attic/potx.inc,v
retrieving revision 1.1.2.17.2.7.2.19.4.8
diff -u -p -r1.1.2.17.2.7.2.19.4.8 potx.inc
--- potx.inc	17 Nov 2009 12:25:18 -0000	1.1.2.17.2.7.2.19.4.8
+++ potx.inc	27 Dec 2009 14:40:40 -0000
@@ -24,7 +24,7 @@
 
 /**
  * The current Drupal major API verion.
- * 
+ *
  * This should be the only difference between different branches of potx.inc
  */
 define('POTX_API_CURRENT', 6);
@@ -1477,7 +1477,7 @@ function _potx_save_string($value = NULL
   global $_potx_strings, $_potx_install;
 
   if (isset($value)) {
-    
+
     // Value set but empty. Mark error on empty translatable string. Only trim
     // for empty string checking, since we should store leading/trailing
     // whitespace as it appears in the string otherwise.
@@ -1486,7 +1486,7 @@ function _potx_save_string($value = NULL
       potx_status('error', t('Empty string attempted to be localized. Please do not leave test code for localization in your source.'), $file, $line);
       return;
     }
-    
+
     switch ($string_mode) {
       case POTX_STRING_BOTH:
         // Mark installer strings as duplicates of runtime strings if
Index: potx.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/potx/Attic/potx.info,v
retrieving revision 1.1.2.3.2.2.2.1
diff -u -p -r1.1.2.3.2.2.2.1 potx.info
--- potx.info	2 Apr 2009 11:05:29 -0000	1.1.2.3.2.2.2.1
+++ potx.info	27 Dec 2009 14:40:40 -0000
@@ -2,5 +2,6 @@
 name = Translation template extractor
 description = Provides a web interface and an API to extract translatable text from the sources of installed components.
 dependencies[] = locale
+dependencies[] = update
 core = 6.x
 package = Multilanguage
Index: potx.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/potx/Attic/potx.module,v
retrieving revision 1.1.2.12.2.2.2.10.4.2
diff -u -p -r1.1.2.12.2.2.2.10.4.2 potx.module
--- potx.module	24 Aug 2009 07:33:08 -0000	1.1.2.12.2.2.2.10.4.2
+++ potx.module	27 Dec 2009 14:40:40 -0000
@@ -27,8 +27,7 @@ function potx_help($path, $arg) {
 function potx_menu() {
   $items['admin/build/translate/extract'] = array(
     'title' => 'Extract',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('potx_select_form'),
+    'page callback' => 'potx_export_page',
     'access arguments' => array('translate interface'),
     'weight' => 200,
     'type' => MENU_LOCAL_TASK,
@@ -37,37 +36,96 @@ function potx_menu() {
 }
 
 /**
+ * Implementation of hook_update_projects_alter().
+ */
+function potx_update_projects_alter(&$projects) {
+  module_load_include('inc', 'update', 'update.compare');
+  $modules = _potx_filter_disabled(module_rebuild_cache());
+  _update_process_info_list($projects, $modules, 'disabled-module');
+  $themes = _potx_filter_disabled(system_theme_data());
+  _update_process_info_list($projects, $themes, 'disabled-theme');
+}
+
+/**
+ * Implementation of hook_theme().
+ */
+function potx_theme() {
+  return array(
+    'potx_select_form' => array(
+      'arguments' => array('form' => NULL),
+    ),
+  );
+}
+
+/**
+ * Page callback for exporting templates and .po files.
+ */
+function potx_export_page() {
+  drupal_add_css(drupal_get_path('module', 'potx') .'/potx.css', 'module');
+  return drupal_get_form('potx_select_form');
+}
+
+/**
  * Component selection interface.
  */
 function potx_select_form() {
 
   $form = array();
-  $components = _potx_component_list();
-  _potx_component_selector($form, $components);
+
+  // Use update information to present a nicer overview. We then have nice
+  // project data about modules and themes which are enabled.
+  module_load_include('inc', 'update', 'update.compare');
+  $update_information = update_get_available();
+  $projects = update_get_projects();
+
+  foreach ($projects as $key => $project) {
+    $subproject_elements = array();
+    if (count($project['includes']) > 1) {
+      foreach($project['includes'] as $subproject_key => $subproject_name) {
+        $subproject_elements[] = array(
+          '#type' => 'radio',
+          '#name' => 'project',
+          '#title' => $subproject_name,
+          '#return_value' => $subproject_key,
+        );
+      }
+    }
+    $title = (isset($update_information[$key]['title']) ? $update_information[$key]['title'] : $project['name']);
+    $form['projects'][] = array(
+      'project' => array(
+        '#type' => 'radio',
+        //'#name' => 'project',
+        '#title' => $title,
+        '#return_value' => $key,
+      ),
+      'subprojects' => $subproject_elements,
+    );
+  }
 
   // Generate translation file for a specific language if possible.
   $languages = language_list();
   if (count($languages) > 1 || !isset($languages['en'])) {
     // We have more languages, or the single language we have is not English.
-    $options = array('n/a' => t('Language independent template'));
+    $form['type'] = array(
+      '#type' => 'radios',
+      '#title' => t('Type'),
+      '#options' => array(0 => t('Include both English originals and translations'), 1 => t('Just export English originals')),
+      '#default_value' => 0,
+    );
+
+    $options = array('n/a' => t('Language independent'));
     foreach ($languages as $langcode => $language) {
       // Skip English, as we should not have translations for this language.
       if ($langcode == 'en') {
         continue;
       }
-      $options[$langcode] = t('Template file for !langname translations', array('!langname' => t($language->name)));
+      $options[$langcode] = t($language->name);
     }
     $form['langcode'] = array(
-      '#type' => 'radios',
-      '#title' => t('Template language'),
+      '#type' => count($options) > 5 ? 'select' : 'radios',
+      '#title' => t('Language'),
       '#default_value' => 'n/a',
       '#options' => $options,
-      '#description' => t('Export a language independent or language dependent (plural forms, language team name, etc.) template.'),
-    );
-    $form['translations'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Include translations'),
-      '#description' => t('Include translations of strings in the file generated. Not applicable for language independent templates.')
     );
   }
 
@@ -80,6 +138,34 @@ function potx_select_form() {
 }
 
 /**
+ * Default theme function for potx project picker.
+ */
+function theme_potx_select_form($form) {
+  $output = '<h3>'. t('Pick a project to extract from') .'</h3>';
+  $output .= '<div id="potx-export-picker">';
+  foreach ($form['projects'] as &$project_element) {
+    if (isset($project_element['project'])) {
+      $has_subprojects = isset($project_element['subprojects'][0]);
+      $output .= '<div class="potx-project"><div class="potx-project-name">';
+      if ($has_subprojects) {
+        $output .= ' <div class="potx-description">('. t('Includes subprojects listed below') .')</div>';
+      }
+      $output .= drupal_render($project_element['project']) .'<div class="clear-block"></div></div>';
+      if ($has_subprojects) {
+        // Check for item [0]. count() is not reliable here due to additional
+        // elements added by FormAPI.
+        $output .= '<div class="potx-subprojects">'. drupal_render($project_element['subprojects']) .'</div>';
+      }
+      $output .= '<div class="clear-block"></div></div>';
+    }
+  }
+  $output .= '</div>';
+  $output .= '<h3>'. t('Configure output format') .'</h3>';
+  $output .= drupal_render($form);
+  return $output;
+}
+
+/**
  * Validation handler for potx component selection form.
  */
 function potx_select_form_validate($form, &$form_state) {
@@ -159,141 +245,51 @@ function potx_select_form_submit($form, 
 }
 
 /**
- * Build a chunk of the component selection form.
- *
- * @param $form
- *   Form to populate with fields.
- * @param $components
- *   Structured array with components as returned by _potx_component_list().
- * @param $dirname
- *   Name of directory handled.
- */
-function _potx_component_selector(&$form, &$components, $dirname = '') {
-
-  // Pop off count of components in this directory.
-  if (isset($components['#-count'])) {
-    $component_count = $components['#-count'];
-    unset($components['#-count']);
-  }
-
-  //ksort($components);
-  $dirkeys = array_keys($components);
-
-  // A directory with one component.
-  if (isset($component_count) && (count($components) == 1)) {
-    $component = array_shift($components);
-    $dirname = dirname($component->filename);
-    $form[_potx_form_id('dir', $dirname)] = array(
-      '#type' => 'radio',
-      '#title' => t('Extract from %name in the %directory directory', array('%directory' => $dirname, '%name' => $component->name)),
-      '#description' => t('Generates output from all files found in this directory.'),
-      '#default_value' => 0,
-      '#return_value' => $dirname,
-      // Get all radio buttons into the same group.
-      '#parents' => array('component'),
-    );
-    return;
-  }
+ * Implementation of hook_system_info_alter().
+ */
+function potx_system_info_alter(&$info, $file) {
+  static $names = array();
 
-  // A directory with multiple components in it.
-  if (preg_match('!/(modules|themes)\\b(/.+)?!', $dirname, $pathmatch)) {
-    $t_args = array('@directory' => substr($dirname, 1));
-    if (isset($pathmatch[2])) {
-      $form[_potx_form_id('dir', $dirname)] = array(
-        '#type' => 'radio',
-        '#title' => t('Extract from all in directory "@directory"', $t_args),
-        '#description' => t('To extract from a single component in this directory, choose the desired entry in the fieldset below.'),
-        '#default_value' => 0,
-        '#return_value' => substr($dirname, 1),
-        // Get all radio buttons into the same group.
-        '#parents' => array('component'),
-      );
-    }
-    $element = array(
-      '#type' => 'fieldset',
-      '#title' => t('Directory "@directory"', $t_args),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-    );
-    $form[_potx_form_id('fs', $dirname)] =& $element;
-  }
-  else {
-    $element =& $form;
-  }
+  if (empty($info['project'])) {
+    if (isset($names[$file->filename])) {
+      $info['project'] = $names[$file->filename];
+      return;
+    }
 
-  foreach ($dirkeys as $entry) {
-    // A component in this directory with multiple components.
-    if ($entry[0] == '#') {
-      // Component entry.
-      $t_args = array(
-        '%directory' => dirname($components[$entry]->filename),
-        '%name'      => $components[$entry]->name,
-        '%pattern'   => $components[$entry]->name .'.*',
-      );
-      $element[_potx_form_id('com', $components[$entry]->basename)] = array(
-        '#type' => 'radio',
-        '#title' => t('Extract from %name', $t_args),
-        '#description' => t('Extract from files named %pattern in the %directory directory.', $t_args),
-        '#default_value' => 0,
-        '#return_value' => $components[$entry]->filename,
-        // Get all radio buttons into the same group.
-        '#parents' => array('component'),
-      );
+    if (module_exists('cvs_deploy') && ($project = cvs_deploy_get_project_name($file))) {
+      // Make sure cvs_deploy has a chance to run before our code.
+      $names[$file->filename] = $info['project'] = $project;
     }
-    // A subdirectory we need to look into.
-    else {
-      _potx_component_selector($element, $components[$entry], "$dirname/$entry");
+    elseif (preg_match('!^(sites|profiles)/(.+)/(modules|themes)/([^/]+)($|/)!', $file->filename, $found)) {
+      // Grab top level directory name for projects hosted under sites/.../modules
+      // or themes as well as at similar places under install profiles. This
+      // might not be correct, but we do not have too much information to decide.
+      $names[$file->filename] = $info['project'] = $found[4];
+    }
+    elseif (preg_match('!^(modules|themes)/(.+)($|/)!', $file->filename, $found)) {
+      // Grab top level directory name for projects hosted under modules/ and
+      // themes/. People should theoretically not put stuff here, but distros,
+      // like Acquia Drupal do to work with the loading order sequence of core.
+      // Again, this might not be correct, but in cases like Acquia Drupal, the
+      // version information should be there in .info files, so we should not
+      // get here anyway. We do not have much information either.
+      $names[$file->filename] = $info['project'] = $found[2];
     }
   }
-
-  return count($components);
 }
 
 /**
- * Generate a sane form element ID for the current radio button.
- *
- * @param $type
- *   Type of ID generated: 'fs' for fieldset, 'dir' for directory, 'com' for component.
- * @param $path
- *   Path of file we generate an ID for.
- * @return
- *   The generated ID.
+ * Look for disabled files in $list and return those as if all are enabled.
  */
-function _potx_form_id($type, $path) {
-  return 'potx-'. $type .'-'. preg_replace('/[^a-zA-Z0-9]+/', '-', $path);
-}
-
-/**
- * Generate a hierarchical structured list of components.
- *
- * @return
- *  Array in the directory structure identified.
- *    - 'normal'  keyed elements being subfolders
- *    - '#name'   elements being component objects for the 'name' component
- *    - '#-count' being the file count of all components in the directory
- */
-function _potx_component_list() {
-  $components = array();
-  // Get a list of all enabled modules and themes.
-  $result = db_query("SELECT name, filename, type, status FROM {system} WHERE type IN ('module', 'theme') ORDER BY filename ASC");
-  while ($component = db_fetch_object($result)) {
-    // Build directory tree structure.
-    $path_parts = explode('/', dirname($component->filename));
-    $dir =& $components;
-    foreach ($path_parts as $dirname) {
-      if (!isset($dir[$dirname])) {
-        $dir[$dirname] = array();
-      }
-      $dir =& $dir[$dirname];
+function _potx_filter_disabled($list) {
+  $disabled = array();
+  foreach ($list as $key => $file) {
+    if (empty($file->status)) {
+      $file->status = 1;
+      $disabled[$key] = $file;
     }
-
-    // Information about components in this directory.
-    $component->basename = basename($component->filename);
-    $dir['#'. $component->basename] = $component;
-    $dir['#-count'] = isset($dir['#-count']) ? $dir['#-count'] + 1 : 1;
   }
-
-  return $components;
+  return $disabled;
 }
 
 /**
