diff --git a/includes/nodequeue.admin.inc b/includes/nodequeue.admin.inc
index 31e51a7..2e032e2 100644
--- a/includes/nodequeue.admin.inc
+++ b/includes/nodequeue.admin.inc
@@ -325,10 +325,27 @@ function nodequeue_edit_queue_form($form, &$form_state, $queue) {
     '#title' => t('Title'),
     '#default_value' => $queue->title,
     '#size' => 50,
+    '#required' => TRUE,
     '#maxlength' => 64,
     '#description' => t('Enter the name of the queue'),
   );
 
+  $form['name'] = array(
+    '#type' => 'machine_name',
+    '#maxlength' => 32,
+    '#machine_name' => array(
+      'exists' => 'nodequeue_machine_name_exists',
+      'source' => array('title'),
+    ),
+    '#description' => t('A unique machine-readable name for this queue. It must only contain lowercase letters, numbers, and underscores.'),
+  );
+
+  if (isset($queue->name)) {
+    $form['name']['#default_value'] = $queue->name;
+    $form['name']['#disabled'] = TRUE;
+    $form['name']['#value'] = $queue->name;
+  }
+
   // This is a value; as the default nodequeue implementation has just one
   // queue per nodequeue, this field is totally redundant. Plugins can
   // override this.
diff --git a/includes/views/nodequeue.views.inc b/includes/views/nodequeue.views.inc
index 595289e..a7ea7cb 100644
--- a/includes/views/nodequeue.views.inc
+++ b/includes/views/nodequeue.views.inc
@@ -109,6 +109,24 @@ function nodequeue_views_data() {
     ),
   );
 
+  $data['nodequeue_queue']['name'] = array(
+    'title' => t('Queue machine name'),
+    'help' => t('The machine name of the queue.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+  );
+
   // ----------------------------------------------------------------
   // nodequeue_queue table
   $data['nodequeue_queue']['table']['group'] = t('Nodequeue');
diff --git a/includes/views/nodequeue_handler_relationship_nodequeue.inc b/includes/views/nodequeue_handler_relationship_nodequeue.inc
index f61460f..5f01029 100644
--- a/includes/views/nodequeue_handler_relationship_nodequeue.inc
+++ b/includes/views/nodequeue_handler_relationship_nodequeue.inc
@@ -1,13 +1,31 @@
 <?php
+
 /**
  * Specialized relationship handler to add nodequeues.
  */
 class nodequeue_handler_relationship_nodequeue extends views_handler_relationship {
+  /**
+   * Init handler to let relationships live on tables other than
+   * the table they operate on.
+   */
+  function init(&$view, &$options) {
+    parent::init($view, $options);
+
+    // Tranlate an older setting which was using qids instead of machine names.
+    if (!empty($options['qids'])) {
+      $map = array_flip(nodequeue_get_qid_map());
+      foreach ($options['qids'] as $key => $value) {
+        $this->options['names'][$map[$key]] = ($value) ? $map[$key] : 0;
+      }
+      unset($this->options['qids']);
+    }
+  }
+
   function option_definition() {
     $options = parent::option_definition();
 
     $options['limit']['default'] = FALSE;
-    $options['qids']['default'] = array();
+    $options['names']['default'] = array();
     return $options;
   }
 
@@ -18,8 +36,6 @@ class nodequeue_handler_relationship_nodequeue extends views_handler_relationshi
   function options_form(&$form, &$form_state) {
     parent::options_form($form, $form_state);
 
-    $queues = nodequeue_load_queues(nodequeue_get_all_qids());
-
     $form['limit'] = array(
       '#type' => 'checkbox',
       '#title' => t('Limit to one or more queues (recommended)'),
@@ -27,21 +43,20 @@ class nodequeue_handler_relationship_nodequeue extends views_handler_relationshi
     );
 
     $options = array();
-
+    $queues = nodequeue_load_queues(nodequeue_get_all_qids(0, 0, TRUE), TRUE);
     foreach ($queues as $queue) {
-      $options[$queue->qid] = $queue->title;
+      $options[$queue->name] = $queue->title;
     }
 
-    $form['qids'] = array(
+    $form['names'] = array(
+      '#prefix' => '<div><div id="edit-options-names">',
+      '#suffix' => '</div></div>',
       '#type' => 'checkboxes',
       '#title' => t('Queues'),
       '#options' => $options,
-      '#default_value' => $this->options['qids'],
-      '#states' => array(
-        'visible' => array(
-          ':input[name="options[limit]"]' => array('checked' => TRUE)
-        ),
-      ),
+      '#default_value' => $this->options['names'],
+      '#process' => array('form_process_checkboxes', 'ctools_dependent_process'),
+      '#dependency' => array('edit-options-limit' => array(TRUE)),
     );
   }
 
@@ -63,17 +78,23 @@ class nodequeue_handler_relationship_nodequeue extends views_handler_relationshi
     }
 
     if (!empty($this->options['limit'])) {
+      $names = array_keys(array_filter($this->options['names']));
+      $qids = array();
+      $map = nodequeue_get_qid_map();
+      foreach ($names as $name) {
+        if (isset($map[$name])) {
+          $qids[] = $map[$name];
+        }
+      }
+
       $join->definition['extra'] = array(array(
         'field' => 'qid',
-        'value' => array_filter($this->options['qids']),
-        'numeric' => TRUE,
+        'value' => $qids,
       ));
     }
 
     $join->construct();
-
     $alias = $join->definition['table'] . '_' . $join->definition['left_table'];
-
     $this->alias = $this->query->add_relationship($alias, $join, 'nodequeue_nodes', $this->relationship);
   }
 }
diff --git a/nodequeue.install b/nodequeue.install
index eccdef9..968abad 100644
--- a/nodequeue.install
+++ b/nodequeue.install
@@ -18,6 +18,11 @@ function nodequeue_schema() {
         'unsigned' => TRUE,
         'not null' => TRUE
       ),
+      'name' => array(
+        'description' => 'The machine name for the queue.',
+        'type' => 'varchar',
+        'length' => 128,
+      ),
       'title' => array(
         'description' => 'Title of a queue.',
         'type' => 'varchar',
@@ -88,6 +93,9 @@ function nodequeue_schema() {
       ),
     ), // fields
     'primary key' => array('qid'),
+    'unique keys' => array(
+      'name' => array('name'),
+    ),
   ); // nodequeue_queue.
   $schema['nodequeue_roles'] = array(
     'description' => 'Defines the roles which are allowed to use a particular nodequeue.',
@@ -333,3 +341,57 @@ function nodequeue_update_7200() {
     }
   }
 }
+
+/**
+ * Provide machine names, and auto-generation of machine names for existing
+ * queues.
+ */
+function nodequeue_update_7201() {
+  // Check that the name field hasn't been created by a 6.x-2.x-dev version
+  // prior to 6.x-2.10.
+  if (!db_field_exists('nodequeue_queue', 'name')) {
+    $name_field = array(
+      'description' => 'The machine name for the queue.',
+      'type' => 'varchar',
+      'length' => 128,
+    );
+    db_add_field('nodequeue_queue', 'name', $name_field);
+    db_add_unique_key('nodequeue_queue', 'name', array('name'));
+
+    // Auto-generate machine names for existing queues and subqueues. Existing
+    // queues will be given the first 128 characters of the title, with all
+    // spaces replaced with underline characters, made lowercase and trimmed
+    // of excess whitespace. Nodequeues with empty titles will receive a name
+    // like 'queue_$qid'.
+    $result = db_query("SELECT qid, title FROM {nodequeue_queue}");
+    foreach ($result as $queue) {
+      if (!empty($queue->title)) {
+        // Basic formatting.
+        $new_name = strtolower(trim(substr(check_plain($queue->title), 0, 128)));
+        // Regex to strip out all unwanted characters.
+        $new_name = preg_replace('/[^a-z0-9_]+/', '_', $new_name);
+
+        // Check if this queue name already exists.
+        if (nodequeue_machine_name_exists($new_name)) {
+          $tmp_name = $new_name;
+          $i = 0;
+          do {
+            // Append an incrementing numeric suffix until we find a unique name.
+            $unique_suffix = '_' . $i;
+            $new_name = truncate_utf8($tmp_name, 128 - drupal_strlen($unique_suffix, TRUE)) . $unique_suffix;
+            $i++;
+          } while (nodequeue_machine_name_exists($new_name));
+        }
+      }
+      else {
+        // Default to a name like 'queue_$qid' for queues that don't have a title.
+        $new_name = 'queue_' . $queue->qid;
+      }
+
+      db_update('nodequeue_queue')
+        ->fields(array('name' => $new_name))
+        ->condition('qid', $queue->qid)
+        ->execute();
+    }
+  }
+}
diff --git a/nodequeue.module b/nodequeue.module
index cfe0d6f..7cb37f8 100644
--- a/nodequeue.module
+++ b/nodequeue.module
@@ -480,6 +480,7 @@ function nodequeue_apachesolr_query_alter(DrupalSolrQueryInterface $query) {
  * always check to see if our variables are empty or not.
  */
 class nodequeue_queue {
+  var $name = '';
   var $title = '';
   var $size = 0;
   var $link = '';
@@ -845,6 +846,7 @@ function nodequeue_load_subqueues_by_reference($references, $bypass_cache = FALS
  */
 function nodequeue_save(&$queue) {
   $nodequeue_queue_fields = array(
+    'name' => $queue->name,
     'title' => $queue->title,
     'subqueue_title' => $queue->subqueue_title,
     'size' => $queue->size,
@@ -1860,6 +1862,48 @@ function _nodequeue_access_admin_or_manipulate() {
 }
 
 /**
+ * Return a queue by its machine name. This is obviously not ideal due to the
+ * extra queries, but probably preferable to changing current API calls.
+ *
+ * @param $name
+ *   The queue machine name
+ *
+ * @return
+ *   The queue definition, or an empty array if no queue was found with the
+ *   given machine name.
+ */
+function nodequeue_load_queue_by_name($name) {
+  $map = nodequeue_get_qid_map();
+  if (isset($map[$name])) {
+    $queues = nodequeue_load_queues(array($map[$name]));
+    if ($queues) {
+      return current($queues);
+    }
+  }
+
+  return array();
+}
+
+
+/**
+ * Return a map of queue name to qid values to aid in various lookups.
+ *
+ * @return array
+ *   A array of qids, keyed by machine name.
+ */
+function nodequeue_get_qid_map() {
+  static $map = array();
+  if (!$map) {
+    $result = db_query("SELECT qid, name FROM {nodequeue_queue}");
+    while ($get = $result->fetchObject()) {
+      $map[$get->name] = $get->qid;
+    }
+  }
+  return $map;
+}
+
+
+/**
  * Used by menu system to determine access to the node and the queue in question.
  *
  * No, this isn't some odd hook_access implementation.
@@ -1971,7 +2015,18 @@ function nodequeue_get_content_id($queue, $node) {
   return ($queue->i18n && !empty($node->tnid)) ? $node->tnid : $node->nid;
 }
 
-/*
+/**
+ * Determine if the machine name is in use.
+ */
+function nodequeue_machine_name_exists($machine_name) {
+  $queue_exists = db_query_range('SELECT 1 FROM {nodequeue_queue} WHERE name = :name', 0, 1, array(':name' => $machine_name))->fetchField();
+
+  return $queue_exists;
+}
+ 
+ /**
+
+/**
  * Get the list of nodes in the subqueue, taking into account node access restrictions.
  */
 function nodequeue_nids_visible($sqid = -1, $account = NULL) {
