diff --git a/addons/nodequeue_service/nodequeue_service.inc b/addons/nodequeue_service/nodequeue_service.inc
index 2fcf3db..62c0262 100644
--- a/addons/nodequeue_service/nodequeue_service.inc
+++ b/addons/nodequeue_service/nodequeue_service.inc
@@ -16,7 +16,7 @@
 function nodequeue_service_get_nodequeues() {
   if (module_exists('nodequeue')) {
     // Fetch all of the queues.
-    $queues = nodequeue_load_queues(nodequeue_get_all_queues(0));
+    $queues = nodequeue_load_multiple(nodequeue_get_all_queues(0));
     if (empty($queues)) {
       return services_error(t('Nodequeue available, but no nodequeues exist.'));
     }
diff --git a/includes/nodequeue.actions.inc b/includes/nodequeue.actions.inc
index 703f615..6a1699d 100644
--- a/includes/nodequeue.actions.inc
+++ b/includes/nodequeue.actions.inc
@@ -40,7 +40,7 @@ function nodequeue_add_action_form($context) {
     $context['queues'] = '';
   }
 
-  $queues = nodequeue_load_queues(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
+  $queues = nodequeue_load_multiple(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
   foreach ($queues as $name => $queue) {
     $options[$name] = $queue->title;
   }
@@ -76,7 +76,7 @@ function nodequeue_add_action_submit($form, &$form_state) {
  * Action to add a node to a queue.
  */
 function nodequeue_add_action($node, $context) {
-  $queues = nodequeue_load_queues($context['queues'], TRUE);
+  $queues = nodequeue_load_multiple($context['queues'], TRUE);
   // Filter out queues by node type. We choose not to use nodequeue_get_queues()
   // because it checks for access control which only matters if we administering
   // a queue.
@@ -116,7 +116,7 @@ function action_nodequeue_add($op, $edit = array(), $node) {
       break;
 
     case 'do':
-      $queues = nodequeue_load_queues($edit['queues'], TRUE);
+      $queues = nodequeue_load_multiple($edit['queues'], TRUE);
       // Filter out queues by node type. We choose not to use
       // nodequeue_get_queues() because it checks for access control which only
       // matters if we administering a queue.
@@ -147,7 +147,7 @@ function action_nodequeue_add($op, $edit = array(), $node) {
       if (!isset($edit['queues'])) {
         $edit['queues'] = '';
       }
-      $queues = nodequeue_load_queues(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
+      $queues = nodequeue_load_multiple(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
       foreach ($queues as $name => $queue) {
         $options[$name] = $queue->title;
       }
@@ -190,7 +190,7 @@ function nodequeue_remove_action_form($context) {
     $context['queues'] = array();
   }
 
-  $queues = nodequeue_load_queues(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
+  $queues = nodequeue_load_multiple(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
   foreach ($queues as $name => $queue) {
     $options[$name] = $queue->title;
   }
@@ -274,7 +274,7 @@ function action_nodequeue_remove($op, $edit = array(), $node) {
         $edit['queues'] = array();
       }
 
-      $queues = nodequeue_load_queues(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
+      $queues = nodequeue_load_multiple(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
       foreach ($queues as $name => $queue) {
         $options[$name] = $queue->title;
       }
diff --git a/includes/nodequeue.admin.inc b/includes/nodequeue.admin.inc
index 9ae8ec7..5ed2a32 100644
--- a/includes/nodequeue.admin.inc
+++ b/includes/nodequeue.admin.inc
@@ -182,7 +182,7 @@ function nodequeue_node_tab($node) {
     $row = array();
     $row[] = array(
       'class' => array('nodequeue-title'),
-      'data' => l(nodequeue_title_substitute($queue->subqueue_title, $queue, $subqueue), "admin/structure/nodequeue/$queue->name/view/$subqueue->sqid"),
+      'data' => l(nodequeue_title_substitute($queue->subqueue_title, $queue, $subqueue), "admin/structure/nodequeue/list/$queue->name/view/$subqueue->sqid"),
     );
     $row[] = array(
       'class' => array('nodequeue-max-nodes'),
@@ -204,125 +204,6 @@ function nodequeue_node_tab($node) {
 }
 
 /**
- * Display a list of queues and their status for the administrator.
- */
-function nodequeue_view_queues() {
-  $output = '';
-
-  if (module_exists('advanced_help')) {
-    $output .= theme('advanced_help_topic', array(
-      'module' => 'nodequeue',
-      'topic' => 'about',
-    ));
-    $output .= '&nbsp;' . theme('advanced_help_topic', array(
-      'module' => 'nodequeue',
-      'topic' => 'about',
-      'type' => t('Click here for information about this module'),
-    ));
-    $output = '<p>' . $output . '</p>';
-  }
-
-  // Fetch all of the queues.
-  $queues = nodequeue_load_queues(nodequeue_get_all_queues(25));
-
-  foreach ($queues as $queue) {
-    if (!nodequeue_queue_access($queue)) {
-      unset($queues[$queue->name]);
-    }
-  }
-
-  if (empty($queues)) {
-    return $output . t('No nodequeues exist.');
-  }
-
-  $header = array(
-    array('data' => t('Title'), 'field' => 'title', 'sort' => 'asc'),
-    array('data' => t('Max nodes'), 'field' => 'size'),
-    array('data' => t('Subqueues'), 'field' => 'subqueues'),
-    array('data' => t('Operation')),
-  );
-  $table_sort = tablesort_init($header);
-
-  $queue_names = array();
-  $sort_primary = array();
-  $sort_secondary = array();
-  $sort_direction_regular = array('asc' => SORT_ASC, 'desc' => SORT_DESC);
-  $sort_direction_reverse = array('asc' => SORT_DESC, 'desc' => SORT_ASC);
-  foreach ($queues as $queue) {
-    // If a queue has only one subqueue, store the name so we can display
-    // the number of nodes in the subqueue.
-    if ($queue->subqueues == 1) {
-      $queue_names[] = $queue->name;
-    }
-    $sort_secondary[] = drupal_strtolower($queue->title);
-    switch ($table_sort['sql']) {
-      case 'title':
-      default:
-        $sort_primary[] = drupal_strtolower($queue->title);
-        $sort_direction = $sort_direction_regular;
-        break;
-      case 'size':
-        $sort_primary[] = $queue->size;
-        $sort_direction = $sort_direction_reverse;
-        break;
-      case 'subqueues':
-        $sort_primary[] = $queue->subqueues;
-        $sort_direction = $sort_direction_regular;
-        break;
-    }
-  }
-
-  $subqueues = nodequeue_load_subqueues_by_queue($queue_names);
-  // Relate all the subqueues we loaded back to our queues.
-  foreach ($subqueues as $subqueue) {
-    if (nodequeue_api_subqueue_access($subqueue, NULL, $queues[$subqueue->name])) {
-      $queues[$subqueue->name]->subqueue = $subqueue;
-    }
-  }
-
-  if (!empty($table_sort)) {
-    if (strtolower($table_sort['sort']) == 'desc') {
-      array_multisort($sort_primary, $sort_direction['desc'], $sort_secondary, $queues); // Re-indexes array keys; key no longer equals name.
-    }
-    else {
-      array_multisort($sort_primary, $sort_direction['asc'], $sort_secondary, $queues); // Re-indexes array keys; key no longer equals name.
-    }
-  }
-
-  $rows = array();
-  foreach ($queues as $queue) {
-    $operations = array();
-    $sub_text = $queue->subqueues;
-
-    // If this queue has only one subqueue.
-    if ($sub_text == 1) {
-      $sub_text .= " (" . nodequeue_subqueue_size_text($queue->size, $queue->subqueue->count) . ")";
-      $operations[] = l(t('View'), "admin/structure/nodequeue/$queue->name/view/" . $queue->subqueue->sqid);
-    }
-    else {
-      $operations[] = l(t('View'), "admin/structure/nodequeue/$queue->name/view");
-    }
-
-    if (user_access('administer nodequeue')) {
-      $operations[] = l(t('Edit'), "admin/structure/nodequeue/$queue->name/edit");
-      $operations[] = l(t('Delete'), "admin/structure/nodequeue/$queue->name/delete");
-    }
-
-    $rows[] = array(
-      array('class' => array('nodequeue-title'), 'data' => check_plain($queue->title)),
-      array('class' => array('nodequeue-max-nodes'), 'data' => $queue->size == 0 ? t('Infinite') : $queue->size),
-      array('class' => array('nodequeue-subqueues'), 'data' => $sub_text),
-      array('class' => array('nodequeue-operation'), 'data' => implode(' | ', $operations)),
-    );
-  }
-
-  $output .= theme('table', array('header' => $header, 'rows' => $rows));
-  $output .= theme('pager', array('tags' => NULL));
-
-  return $output;
-}
-
-/**
  * Display a list of subqueues for a queue and their sizes
  */
 function nodequeue_view_subqueues($queue) {
@@ -338,7 +219,7 @@ function nodequeue_view_subqueues($queue) {
       $rows[] = array(
         array('class' => array('nodequeue-title'), 'data' => check_plain($subqueue->title)),
         array('class' => array('nodequeue-subqueues'), 'data' => $sub_text),
-        array('class' => array('nodequeue-operation'), 'data' => l(t('View'), "admin/structure/nodequeue/$queue->name/view/$subqueue->sqid"))
+        array('class' => array('nodequeue-operation'), 'data' => l(t('View'), "admin/structure/nodequeue/list/$queue->name/view/$subqueue->sqid"))
       );
     }
   }
@@ -351,312 +232,6 @@ function nodequeue_view_subqueues($queue) {
 }
 
 /**
- * Add or edit a queue.
- */
-function nodequeue_edit_queue_form($form, &$form_state, $queue) {
-  $info = nodequeue_api_info();
-
-  // For adding queues.
-  if (is_string($queue)) {
-    // If the $queue is a string - name of a queue type, basically - then we test that it's a valid queue type.
-    $queue = strtolower($queue);
-    if (!isset($info[$queue])) {
-      return FALSE;
-    }
-    drupal_set_title(t('Add @type', array('@type' => $info[$queue]['title'])), PASS_THROUGH);
-    $queue = new nodequeue_queue($queue);
-    $queue->new = TRUE;
-  }
-  else {
-    drupal_set_title(t("Nodequeue '@title'", array('@title' => $queue->title)), PASS_THROUGH);
-  }
-
-  $form['description'] = array(
-    '#type' => 'fieldset',
-    '#title' => filter_xss($info[$queue->owner]['title']),
-    '#description' => filter_xss($info[$queue->owner]['description']),
-  );
-
-  $form['title'] = array(
-    '#type' => 'textfield',
-    '#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 (!empty($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.
-  $form['subqueue_title'] = array(
-    '#type' => 'value',
-    '#value' => $queue->subqueue_title,
-  );
-  // The placeholder is put here so that modifiers have an easy way to put
-  // additional form widgets in a prominent spot but not before the title of
-  // the queue.
-  $form['placeholder'] = array();
-
-  $form['size'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Queue size'),
-    '#default_value' => $queue->size,
-    '#size' => 2,
-    '#maxlength' => 2,
-    '#description' => t('The maximum number of nodes will appear in the queue. Enter 0 for no limit'),
-  );
-
-  $form['reverse'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Reverse in admin view'),
-    '#default_value' => $queue->reverse,
-    '#description' => t('Ordinarily queues are arranged with the front of the queue (where items will be removed) on top and the back (where items will be added) on the bottom. If checked, this will display the queue such that items will be added to the top and removed from the bottom.'),
-  );
-
-  $form['link'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Link "add to queue" text'),
-    '#default_value' => $queue->link,
-    '#size' => 40,
-    '#maxlength' => 40,
-    '#description' => t('If you want a link to add a node to a queue in the "links" section (next to "add new comment"), enter the text here. If left blank no link will be given; note that enabling this feature for any queue will cause an extra query to be run every time a node is loaded. "%subqueue" will be replaced with the subqueue title, if applicable.'),
-  );
-
-  $form['link_remove'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Link "remove from queue" text'),
-    '#default_value' => $queue->link_remove,
-    '#size' => 40,
-    '#maxlength' => 40,
-    '#description' => t('Enter the text for the corresponding link to remove a node from a queue. This may be blank (in which case no link will appear) but a remove link will only appear if link, above, is set.'),
-  );
-
-  $manipulate_all_queues = user_roles(FALSE, 'manipulate all queues');
-  $manipulate_queues = user_roles(FALSE, 'manipulate queues');
-  $roles = $manipulate_all_queues + $manipulate_queues;
-
-  if (!empty($roles)) {
-    $form['roles'] = array(
-      '#type' => 'checkboxes',
-      '#title' => t('Roles'),
-      '#default_value' => is_array($queue->roles) ? $queue->roles : array(),
-      '#options' => $roles,
-      '#description' => t('Check each role that can add nodes to the queue. Be sure that roles you want to appear here have "manipulate queues" access in the main access control panel.'),
-    );
-
-    foreach ($roles as $rid => $role) {
-      $form['roles'][$rid] = array(
-        '#type' => 'checkbox',
-        '#title' => $role,
-        '#default_value' => (isset($manipulate_all_queues[$rid]) || in_array($rid, $queue->roles)) ? TRUE : FALSE,
-        '#disabled' => (isset($manipulate_all_queues[$rid])) ? TRUE : FALSE,
-      );
-    }
-  }
-  else {
-    $form['roles'] = array(
-      '#type' => 'value',
-      '#value' => array(),
-    );
-
-    $form['roles_markup'] = array(
-      '#type' => 'item',
-      '#title' => t('Roles'),
-      '#description' => '<strong>' . t('No roles have the "manipulate queues" permission, so only the administrator account will be able to add or remove items from this queue.') . '</strong>',
-    );
-  }
-
-  $nodes = node_type_get_names();
-
-  $form['types'] = array(
-    '#type' => 'checkboxes',
-    '#title' => t('Types'),
-    '#default_value' => $queue->types,
-    '#options' => $nodes,
-    '#description' => t('Check each node type that can be added to this queue.'),
-  );
-
-  $form['i18n'] = array(
-    '#type' => 'radios',
-    '#title' => t('Internationalization'),
-    '#options' => array(
-      '1' => t('Treat translation nodes as a single node'),
-      '0' => t('Manually manage translated nodes'),
-    ),
-    '#default_value' => $queue->new && module_exists('translation') ? 0 : $queue->i18n,
-    '#description' => t('Treating translations as a single node allows users to add, remove and manipulate a node
-      in the queue regardless of which translation is acted upon; nodequeue will only act on the original node.
-      When manually managing translation nodes, Nodequeue will ignore the relationship between node translations;
-      each translation node must be added to the queue separately and will occupy a separate spot in the queue.
-      Changing this setting will <strong>not</strong> update content that is already in the queue.'),
-    '#access' => module_exists('translation'),
-  );
-
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Submit'),
-  );
-
-  $form['owner'] = array(
-    '#type' => 'value',
-    '#value' => $queue->owner,
-  );
-
-  $form['show_in_links'] = array(
-    '#type' => 'value',
-    '#value' => $queue->show_in_links,
-  );
-
-  $form['show_in_tab'] = array(
-    '#type' => 'value',
-    '#value' => $queue->show_in_tab,
-  );
-
-  $form['show_in_ui'] = array(
-    '#type' => 'value',
-    '#value' => $queue->show_in_ui,
-  );
-
-  $form['reference'] = array(
-    '#type' => 'value',
-    '#value' => $queue->reference,
-  );
-
-  $form['subqueues'] = array(
-    '#type' => 'value',
-    '#value' => $queue->subqueues,
-  );
-
-  // Pass this value along as this may be useful down the road.
-  $form['new'] = array(
-    '#type' => 'value',
-    '#value' => $queue->new,
-  );
-
-  // Queue_names change empty($queue->name) for proper check if existing queue.
-  if (!$queue->new) {
-    $form[] = array(
-      '#type' => 'submit',
-      '#value' => t('Delete'),
-      '#validate' => array('nodequeue_edit_queue_form_delete_validate'),
-      '#submit' => array('nodequeue_edit_queue_form_delete_submit'),
-    );
-    $form['count'] = array(
-      '#type' => 'value',
-      '#value' => $queue->count,
-    );
-  }
-
-  nodequeue_api_queue_form($queue, $form);
-
-  return $form;
-}
-
-/**
- * Validate function for the nodequeue_queue form.
- */
-function nodequeue_edit_queue_form_validate($form, &$form_state) {
-  if (empty($form_state['values']['title'])) {
-    form_set_error('title', t('Please enter a title for this queue.'));
-  }
-  $queue = (object) $form_state['values'];
-  // Fix checkboxes.
-  $queue->roles = array_keys(array_filter($queue->roles));
-  $queue->types = array_keys(array_filter($queue->types));
-
-  nodequeue_api_queue_form_validate($queue, $form_state, $form);
-}
-
-/**
- * Submit function for the nodequeue_queue form.
- */
-function nodequeue_edit_queue_form_submit($formid, &$form_state) {
-  $queue = (object) $form_state['values'];
-  // Fix checkboxes.
-  $queue->roles = array_keys(array_filter($queue->roles));
-  $queue->types = array_keys(array_filter($queue->types));
-
-  // Remove roles that have the 'manipulate all queues' permission.
-  $manipulate_all_queues = array_keys(user_roles(FALSE, 'manipulate all queues'));
-  $queue->roles = array_diff($queue->roles, $manipulate_all_queues);
-
-  // Modify show_in_links based on whether or not links are available.
-  $queue->show_in_links = !empty($queue->link) || !empty($queue->link_remove);
-
-  nodequeue_api_queue_form_submit($queue, $form_state);
-
-  nodequeue_save($queue);
-
-  nodequeue_api_queue_form_submit_finish($queue, $form_state);
-
-  nodequeue_check_subqueue_sizes($queue);
-
-  if (!empty($queue->new)) {
-    drupal_set_message(t('The queue has been created.'));
-  }
-  else {
-    drupal_set_message(t('The queue has been updated.'));
-  }
-  $form_state['redirect'] = 'admin/structure/nodequeue';
-}
-
-/**
- * Delete-validate function for the nodequeue_queue form.
- */
-function nodequeue_edit_queue_form_delete_validate($form, &$form_state) {
-  // No validation for delete step!  But we need to have this so the default validation isn't called.
-}
-
-/**
- * Delete-submit function for the nodequeue_queue form.
- */
-function nodequeue_edit_queue_form_delete_submit($formid, &$form_state) {
-  $form_state['redirect'] = "admin/structure/nodequeue/" . $form_state['values']['name'] . "/delete";
-}
-
-/**
- * Confirm form to delete a queue
- */
-function nodequeue_admin_delete($form, &$form_state, $queue) {
-  $form['name'] = array('#type'  => 'value', '#value' => $queue->name);
-  return confirm_form($form,
-    t('Are you sure you want to delete "%title"?', array('%title' => $queue->title)),
-    isset($_GET['destination']) ? $_GET['destination'] : 'admin/structure/nodequeue',
-    t('This action cannot be undone.'),
-    t('Delete'), t('Cancel')
-  );
-}
-
-/**
- * Submit function for nodequeue delete
- */
-function nodequeue_admin_delete_submit($formid, &$form_state) {
-  if ($form_state['values']['confirm']) {
-    nodequeue_delete($form_state['values']['name']);
-    drupal_set_message(t('The queue has been deleted.'));
-  }
-  $form_state['redirect'] = 'admin/structure/nodequeue';
-}
-
-/**
  * Page callback to view a queue.
  */
 function nodequeue_admin_view($queue, $subqueue = array()) {
@@ -683,7 +258,7 @@ function nodequeue_admin_view($queue, $subqueue = array()) {
     drupal_set_title(t("Subqueue '@title'",
       array('@title' => nodequeue_title_substitute($queue->subqueue_title, $queue, $subqueue))), PASS_THROUGH);
     $breadcrumb = drupal_get_breadcrumb();
-    $breadcrumb[] = l($queue->title, "admin/structure/nodequeue/$queue->name");
+    $breadcrumb[] = l($queue->title, "admin/structure/nodequeue/list/$queue->name");
     drupal_set_breadcrumb($breadcrumb);
   }
   return nodequeue_arrange_subqueue($queue, $subqueue);
@@ -1016,7 +591,7 @@ function nodequeue_save_subqueue_order($nodes, $name, $sqid) {
 }
 
 function nodequeue_arrange_subqueue_form_clear_submit($form, &$form_state) {
-  $form_state['redirect'] = 'admin/structure/nodequeue/' . $form['nodes']['#queue']['name'] . '/clear/' . $form['#subqueue']['sqid'];
+  $form_state['redirect'] = 'admin/structure/nodequeue/list/' . $form['nodes']['#queue']['name'] . '/clear/' . $form['#subqueue']['sqid'];
 }
 
 function nodequeue_arrange_subqueue_form_add_submit($form, &$form_state) {
@@ -1066,7 +641,7 @@ function nodequeue_clear_confirm($form, &$form_state, $queue, $subqueue) {
 
   return confirm_form($form,
     t('Are you sure you want to clear the nodequeue %queue?', array('%queue' => nodequeue_title_substitute($queue->subqueue_title, $queue, $subqueue))),
-    isset($_GET['destination']) ? $_GET['destination'] : 'admin/structure/nodequeue/' . $queue->name . '/view/' . $subqueue->sqid,
+    isset($_GET['destination']) ? $_GET['destination'] : 'admin/structure/nodequeue/list/' . $queue->name . '/view/' . $subqueue->sqid,
     t('This action will remove all nodes from the queue and cannot be undone.'),
     t('Clear'), t('Cancel')
   );
@@ -1079,7 +654,7 @@ function nodequeue_clear_confirm_submit($form, &$form_state) {
   if ($form_state['values']['confirm']) {
     nodequeue_queue_clear($form_state['values']['sqid']);
     drupal_set_message(t('The queue has been cleared.'));
-    $form_state['redirect'] = 'admin/structure/nodequeue/' . $form_state['values']['name'] . '/view/' . $form_state['values']['sqid'];
+    $form_state['redirect'] = 'admin/structure/nodequeue/list/' . $form_state['values']['name'] . '/view/' . $form_state['values']['sqid'];
   }
 }
 
diff --git a/includes/views/nodequeue.views_default.inc b/includes/views/nodequeue.views_default.inc
index be21cc3..87b281b 100644
--- a/includes/views/nodequeue.views_default.inc
+++ b/includes/views/nodequeue.views_default.inc
@@ -12,7 +12,7 @@ function nodequeue_views_default_views() {
     return $views;
   }
 
-  $queues = nodequeue_load_queues(nodequeue_get_all_queues());
+  $queues = nodequeue_load_multiple(nodequeue_get_all_queues());
   foreach ($queues as $queue) {
     $view = new view;
     $view->name = "nodequeue_$queue->name";
diff --git a/includes/views/nodequeue_handler_field_all_queues.inc b/includes/views/nodequeue_handler_field_all_queues.inc
index 090e879..61bae1f 100644
--- a/includes/views/nodequeue_handler_field_all_queues.inc
+++ b/includes/views/nodequeue_handler_field_all_queues.inc
@@ -38,7 +38,7 @@ class nodequeue_handler_field_all_queues extends views_handler_field_prerender_l
     );
 
     $options = array();
-    $queues = nodequeue_load_queues(nodequeue_get_all_queues());
+    $queues = nodequeue_load_multiple(nodequeue_get_all_queues());
     foreach ($queues as $queue) {
       $options[$queue->name] = $queue->title;
     }
diff --git a/includes/views/nodequeue_handler_relationship_nodequeue.inc b/includes/views/nodequeue_handler_relationship_nodequeue.inc
index a066747..58a44d7 100644
--- a/includes/views/nodequeue_handler_relationship_nodequeue.inc
+++ b/includes/views/nodequeue_handler_relationship_nodequeue.inc
@@ -35,7 +35,7 @@ class nodequeue_handler_relationship_nodequeue extends views_handler_relationshi
     );
 
     $options = array();
-    $queues = nodequeue_load_queues(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
+    $queues = nodequeue_load_multiple(nodequeue_get_all_queues(0, 0, TRUE), TRUE);
     foreach ($queues as $queue) {
       $options[$queue->name] = $queue->title;
     }
diff --git a/nodequeue.info b/nodequeue.info
index 16da04c..c27f273 100644
--- a/nodequeue.info
+++ b/nodequeue.info
@@ -4,6 +4,9 @@ package = Nodequeue
 core = 7.x
 configure = admin/structure/nodequeue/settings
 
+; Dependencies
+dependencies[] = ctools
+
 ; Includes
 files[] = includes/views/nodequeue.views.inc
 files[] = includes/nodequeue.actions.inc
diff --git a/nodequeue.install b/nodequeue.install
index 1c22186..ec33cd6 100644
--- a/nodequeue.install
+++ b/nodequeue.install
@@ -11,6 +11,24 @@
 function nodequeue_schema() {
   $schema['nodequeue_queue'] = array(
     'description' => 'Base table for queues, storing global information for each queue',
+    'export' => array(
+      'key' => 'name',
+      'identifier' => 'queue',
+      'default hook' => 'nodequeue_default_queues',
+      'api' => array(
+        'owner' => 'nodequeue',
+        'api' => 'nodequeue_default',
+        'minimum_version' => 3,
+        'current_version' => 3,
+      ),
+      // The callback to load the subqueues, roles and node types.
+      'subrecords callback' => 'nodequeue_process_queues',
+      // CRUD callbacks.
+      'create callback' => 'nodequeue_new_queue',
+      'save callback' => 'nodequeue_save_queue',
+      'delete callback' => 'nodequeue_delete_queue',
+      'export callback' => 'nodequeue_export_queue',
+    ),
     'fields' => array(
       'name' => array(
         'description' => 'The machine name for the queue.',
diff --git a/nodequeue.module b/nodequeue.module
index 4f7c020..4545bd8 100644
--- a/nodequeue.module
+++ b/nodequeue.module
@@ -59,23 +59,6 @@ function nodequeue_menu() {
   $items = array();
   $admin_access = array('administer nodequeue');
 
-  // administrative items
-  $items['admin/structure/nodequeue'] = array(
-    'title' => 'Nodequeues',
-    'page callback' => 'nodequeue_view_queues',
-    'access callback' => '_nodequeue_access_admin_or_manipulate',
-    'description' => 'Create and maintain simple nodequeues.',
-    'file' => 'includes/nodequeue.admin.inc',
-    'type' => MENU_NORMAL_ITEM
-  );
-  $items['admin/structure/nodequeue/list'] = array(
-    'title' => 'List',
-    'page callback' => 'nodequeue_view_queues',
-    'access callback' => '_nodequeue_access_admin_or_manipulate',
-    'file' => 'includes/nodequeue.admin.inc',
-    'weight' => -1,
-    'type' => MENU_DEFAULT_LOCAL_TASK
-  );
   $items['admin/structure/nodequeue/settings'] = array(
     'title' => 'Settings',
     'page callback' => 'drupal_get_form',
@@ -91,18 +74,6 @@ function nodequeue_menu() {
     'file' => 'includes/nodequeue.admin.inc',
     'type' => MENU_CALLBACK
   );
-  $info = nodequeue_api_info();
-  foreach ($info as $key => $data) {
-    $items['admin/structure/nodequeue/add/' . $key] = array(
-      'title' => 'Add @type',
-      'title arguments' => array('@type' => strtolower($data['title'])),
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('nodequeue_edit_queue_form', $key),
-      'access arguments' => $admin_access,
-      'file' => 'includes/nodequeue.admin.inc',
-      'type' => MENU_LOCAL_ACTION
-    );
-  }
   $items['node/%node/nodequeue'] = array(
     'title' => '@tab',
     'title arguments' => array('@tab' => variable_get('nodequeue_tab_name', 'Nodequeue')),
@@ -114,55 +85,6 @@ function nodequeue_menu() {
     'weight' => 5,
     'type' => MENU_LOCAL_TASK
   );
-
-  // Administrative items for an individual queue.
-  $items['admin/structure/nodequeue/%nodequeue'] = array(
-    'page callback' => 'nodequeue_admin_view',
-    'page arguments' => array(3),
-    'access callback' => 'nodequeue_queue_access',
-    'access arguments' => array(3),
-    'file' => 'includes/nodequeue.admin.inc',
-    'type' => MENU_CALLBACK
-  );
-  $items['admin/structure/nodequeue/%nodequeue/view'] = array(
-    'title' => 'View',
-    'page callback' => 'nodequeue_admin_view',
-    'page arguments' => array(3),
-    'access callback' => 'nodequeue_queue_access',
-    'access arguments' => array(3),
-    'file' => 'includes/nodequeue.admin.inc',
-    'weight' => -10,
-    'type' => MENU_DEFAULT_LOCAL_TASK
-  );
-  $items['admin/structure/nodequeue/%nodequeue/view/%subqueue'] = array(
-    'title' => 'View',
-    'page callback' => 'nodequeue_admin_view',
-    'page arguments' => array(3, 5),
-    'access callback' => 'nodequeue_queue_access',
-    'access arguments' => array(3, 5),
-    'file' => 'includes/nodequeue.admin.inc',
-    'weight' => -10,
-    'tab parent' => 'admin/structure/nodequeue/%',
-    'type' => MENU_CALLBACK
-  );
-  // Actual administrative items.
-  $items['admin/structure/nodequeue/%nodequeue/edit'] = array(
-    'title' => 'Edit queue',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('nodequeue_edit_queue_form', 3),
-    'access arguments' => $admin_access,
-    'file' => 'includes/nodequeue.admin.inc',
-    'type' => MENU_LOCAL_TASK
-  );
-  $items['admin/structure/nodequeue/%nodequeue/delete'] = array(
-    'title' => 'Delete',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('nodequeue_admin_delete', 3),
-    'access arguments' => $admin_access,
-    'file' => 'includes/nodequeue.admin.inc',
-    'weight' => 5,
-    'type' => MENU_CALLBACK
-  );
   $items['nodequeue/%nodequeue/add-node/%subqueue/%node'] = array(
     'page callback' => 'nodequeue_admin_add_node',
     'page arguments' => array(1, 3, 4),
@@ -179,15 +101,6 @@ function nodequeue_menu() {
     'file' => 'includes/nodequeue.admin.inc',
     'type' => MENU_CALLBACK
   );
-  $items["admin/structure/nodequeue/%nodequeue/clear/%subqueue"] = array(
-    'title' => 'Clear',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('nodequeue_clear_confirm', 3, 5),
-    'access callback' => 'nodequeue_queue_access',
-    'access arguments' => array(3, 5),
-    'file' => 'includes/nodequeue.admin.inc',
-    'type' => MENU_CALLBACK
-  );
 
   return $items;
 }
@@ -223,8 +136,7 @@ function nodequeue_node_delete($node) {
     // If the queue is being tracked by translation set and the node is part
     // of a translation set, don't delete the queue record.
     // Instead, data will be updated in the 'translation_change' op, below.
-    $queues = nodequeue_load_queues(array($obj->name));
-    $queue = array_shift($queues);
+    $queue = nodequeue_load($obj->name);
     if (!$queue->i18n || (isset($node->tnid) && empty($node->tnid))) {
       // This removes by nid, not position, because if we happen to have a
       // node in a queue twice, the 2nd position would be wrong.
@@ -336,6 +248,17 @@ function nodequeue_views_api() {
   );
 }
 
+/**
+ * Implements hook_ctools_plugin_directory().
+ *
+ * Tell CTools where to search for the export_ui plugin.
+ */
+function nodequeue_ctools_plugin_directory($owner, $type) {
+  if ($owner == 'ctools' && $type =='export_ui') {
+    return 'plugins';
+  }
+}
+
 // --------------------------------------------------------------------------
 // Nodequeue Apache Solr Search Integration
 
@@ -380,7 +303,7 @@ function nodequeue_apachesolr_update_index(&$document, $node) {
     return;
   }
 
-  $queues = nodequeue_load_queues(array_keys(nodequeue_get_all_queues()));
+  $queues = nodequeue_load_multiple(array_keys(nodequeue_get_all_queues()));
   $subqueues = nodequeue_get_subqueues_by_node($queues, $node);
 
   nodequeue_set_subqueue_positions($subqueues, $node->nid);
@@ -470,6 +393,20 @@ class nodequeue_queue {
 }
 
 /**
+ * Create an empty nodequeue to work with.
+ *
+ * @return nodequeue
+ *   A fully formed, empty $queue object. This object must be populated before
+ *   it can be successfully saved.
+ *
+ * @todo Need to find a better way to pass the queue type in a way that works
+ * with ctools export.
+ */
+function nodequeue_new_queue($type = 'nodequeue') {
+  return new nodequeue_queue($type);
+}
+
+/**
  * Fetch a list of available queues for a given location. These queues
  * will be fully loaded and ready to go.
  */
@@ -478,7 +415,7 @@ function nodequeue_load_queues_by_type($type, $location = NULL, $account = NULL,
   if ($location) {
     nodequeue_filter_queues($queues, $location);
   }
-  return nodequeue_load_queues(array_keys($queues), $bypass_cache);
+  return nodequeue_load_multiple(array_keys($queues), $bypass_cache);
 }
 
 /**
@@ -587,80 +524,95 @@ function nodequeue_get_all_queues($page_size = 0, $pager_element = 0, $bypass_ca
 }
 
 /**
- * Load an array of $queues.
+ * Load multiple queues.
  *
- * This exists to provide a way of loading a bunch of queues with
- * the fewest queries. Loading 5 queues results in only 4 queries,
- * not 20. This also caches queues so that they don't get loaded
- * repeatedly.
- *
- * @param $queue_names
+ * @param $names
  *   An array of queue names to load.
- *
- * @param $bypass_cache
- *   Boolean value indicating whether to bypass the cache or not.
+ * @param $reset
+ *   Boolean value indicating whether to reset the cache or not.
  */
-function nodequeue_load_queues($queue_names = array(), $bypass_cache = FALSE) {
-  static $cache = array();
-  $to_load = $loaded = array();
-
-  foreach ($queue_names as $name) {
-    if ($bypass_cache || !isset($cache[$name])) {
-      $to_load[] = $name;
-    }
+function nodequeue_load_multiple($names, $reset = FALSE) {
+  // Sometimes we can expect $names to be an empty array. And when it occurs,
+  // caller expect this to return an empty array.
+  if (empty($names)) {
+    return array();
   }
 
-  if (!empty($to_load)) {
-    $result = db_query("SELECT q.*, COUNT(s.sqid) AS subqueues FROM {nodequeue_queue} q LEFT JOIN {nodequeue_subqueue} s ON q.name = s.name WHERE q.name IN (:to_load) GROUP BY q.name", array(':to_load' => $to_load));
+  ctools_include('export');
 
-    foreach ($result as $queue) {
-      $loaded[$queue->name] = $queue;
-      // ensure valid defaults:
-      $loaded[$queue->name]->types = array();
-      $loaded[$queue->name]->roles = array();
-      $loaded[$queue->name]->count = 0;
-    }
+  if ($reset) {
+    // Clear static cache and make it load from the database again.
+    drupal_static_reset('ctools_export_load_object');
+    drupal_static_reset('ctools_export_load_object_all');
+  }
 
-    $result = db_query("SELECT name, rid FROM {nodequeue_roles} WHERE name IN (:to_load)", array(':to_load' => $to_load));
-    foreach ($result as $obj) {
-      $loaded[$obj->name]->roles[] = $obj->rid;
-    }
+  $queues = ctools_export_load_object('nodequeue_queue', 'names', $names);
 
-    $result = db_query("SELECT name, type FROM {nodequeue_types} WHERE name IN (:to_load)", array(':to_load' => $to_load));
-    foreach ($result as $obj) {
-      $loaded[$obj->name]->types[] = $obj->type;
-    }
+  // This string needs to be on a variable, since it's passed by reference.
+  $context = 'load_queues';
+  drupal_alter('nodequeue', $queues, $context);
 
-    $context = 'load_queues';
-    drupal_alter('nodequeue', $loaded, $context);
-  }
+  return array_filter($queues);
+}
 
-  if ($bypass_cache) {
-    return $loaded;
-  }
-  else {
-    if (!empty($loaded)) {
-      $cache += $loaded;
-    }
-    $queues = array();
-    foreach ($queue_names as $name) {
-      if (isset($cache[$name])) {
-        $queues[$name] = $cache[$name];
-      }
-    }
-    return $queues;
+/**
+ * Process a list of queues, adding all related data.
+ *
+ * @param $queues
+ *   An array of queuess to process.
+ */
+function nodequeue_process_queues(&$queues) {
+  foreach ($queues as &$queue) {
+    nodequeue_process_queue($queue);
   }
 }
 
 /**
+ * Add all data related to a single queue.
+ *
+ * @param $queue
+ *   A pre-loaded queue object.
+ */
+function nodequeue_process_queue(&$queue) {
+  $queue->roles = db_select('nodequeue_roles', 'nr')
+    ->fields('nr', array('rid'))
+    ->condition('nr.name', $queue->name)
+    ->execute()
+    ->fetchAll(PDO::FETCH_COLUMN);
+
+  $queue->types = db_select('nodequeue_types', 'nt')
+    ->fields('nt', array('type'))
+    ->condition('nt.name', $queue->name)
+    ->execute()
+    ->fetchAll(PDO::FETCH_COLUMN);
+
+  $queue->subqueues = db_select('nodequeue_subqueue', 'ns')
+    ->fields('ns', array('reference', 'title'))
+    ->condition('ns.name', $queue->name)
+    ->execute()
+    ->fetchAllKeyed();
+
+  // Reset queue counter.
+  $queue->count = 0;
+
+  return $queue;
+}
+
+/**
  * Load a nodequeue.
  *
  * @param $name
  *   The name of the queue to load.
+ * @return
+ *   An object representing a specific queue.
  */
 function nodequeue_load($name) {
-  $queues = nodequeue_load_queues(array($name));
-  return !empty($queues) ? array_shift($queues) : array();
+  // Use CTools export API to fetch this queue.
+  ctools_include('export');
+  $result = ctools_export_load_object('nodequeue_queue', 'names', array($name));
+  if (isset($result[$name])) {
+    return $result[$name];
+  }
 }
 
 /**
@@ -727,7 +679,6 @@ function nodequeue_load_subqueue($sqid, $bypass_cache = FALSE) {
   if ($subqueues) {
     return array_shift($subqueues);
   }
-
 }
 
 /**
@@ -919,6 +870,34 @@ function nodequeue_delete($name) {
 }
 
 /**
+ * Export CRUD callback to save a queue.
+ */
+function nodequeue_save_queue(&$queue) {
+  return nodequeue_save($queue);
+}
+
+/**
+ * Export CRUD callback to delete a queue.
+ */
+function nodequeue_delete_queue(&$queue) {
+  return nodequeue_delete($queue->name);
+}
+
+/**
+ * Export CRUD callback to export a queue.
+ */
+function nodequeue_export_queue($queue, $indent = '') {
+  ctools_include('export');
+  $output = ctools_export_object('nodequeue_queue', $queue, $indent);
+  $schema = ctools_export_get_schema('nodequeue_queue');
+  $identifier = $schema['export']['identifier'];
+  $output .= $indent . '$' . $identifier . '->roles = ' . ctools_var_export($queue->roles, $indent) . ";\n";
+  $output .= $indent . '$' . $identifier . '->types = ' . ctools_var_export($queue->types, $indent) . ";\n";
+  $output .= $indent . '$' . $identifier . '->subqueues = ' .ctools_var_export($queue->subqueues, $indent). ";\n";
+  return $output;
+}
+
+/**
  * Add a new subqueue to a queue.
  *
  * @param $queue
@@ -1999,15 +1978,6 @@ function nodequeue_get_content_id($queue, $node) {
 }
 
 /**
- * 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) {
diff --git a/nodequeue_generate.module b/nodequeue_generate.module
index 1e087be..f74d0b8 100644
--- a/nodequeue_generate.module
+++ b/nodequeue_generate.module
@@ -24,7 +24,7 @@ function nodequeue_generate_form() {
     '#markup' => '<p>' . t('Select which queues shall be <strong>emptied</strong> and re-populated with new nodes.') . '</p>'
   );
 
-  $queues = nodequeue_load_queues(nodequeue_get_all_queues(25));
+  $queues = nodequeue_load_multiple(nodequeue_get_all_queues(25));
 
   // Tableselect header.
   $header = array(
@@ -96,7 +96,7 @@ function nodequeue_generate_repopulate_queues($queues, $nodes_limit = 10) {
   db_query("DELETE FROM {nodequeue_nodes} WHERE name IN (:queues)", array(':queues' => $queues));
 
   // Load all queues and their subqueues.
-  $queues = nodequeue_load_queues($queues);
+  $queues = nodequeue_load_multiple($queues);
   $subqueues = nodequeue_load_subqueues_by_queue($queues);
 
   // Re-populate subqueues
diff --git a/plugins/nodequeue_ctools_export_ui.class.php b/plugins/nodequeue_ctools_export_ui.class.php
new file mode 100644
index 0000000..2d05e26
--- /dev/null
+++ b/plugins/nodequeue_ctools_export_ui.class.php
@@ -0,0 +1,138 @@
+<?php
+
+/**
+ * @file
+ * Overrides some methods to improve nodequeues list table.
+ */
+
+class nodequeue_ctools_export_ui extends ctools_export_ui {
+
+  function init($plugin) {
+    $prefix_count = count(explode('/', $plugin['menu']['menu prefix']));
+
+    $info = nodequeue_api_info();
+    unset($plugin['menu']['items']['add']);
+    foreach ($info as $key => $data) {
+      $plugin['menu']['items']['add_' . $key] = array(
+        'path' => 'add_' . $key,
+        'title' => 'Add @type',
+        'title arguments' => array('@type' => strtolower($data['title'])),
+        'page callback' => 'ctools_export_ui_switcher_page',
+        'page arguments' => array($plugin['name'], 'add', $key),
+        'load arguments' => array($plugin['name']),
+        'access callback' => 'ctools_export_ui_task_access',
+        'access arguments' => array($plugin['name'], 'add', $key),
+        //'tab parent' => 'admin/structure/nodequeue/%',
+        'type' => MENU_LOCAL_ACTION
+      );
+      // Need to add new items to allowed operations so they show up.
+      $plugin['allowed operations']['add_' . $key] = array('title' => t('Add @type', array('@type' => strtolower($data['title']))));
+    }
+
+    $plugin['menu']['items']['view'] = array(
+      'path' => 'list/%ctools_export_ui/view',
+      'title' => 'View',
+      'page callback' => 'ctools_export_ui_switcher_page',
+      'page arguments' => array($plugin['name'], 'view', $prefix_count + 2),
+      'load arguments' => array($plugin['name']),
+      'access callback' => 'ctools_export_ui_task_access',
+      'access arguments' => array($plugin['name'], 'view', $prefix_count + 2),
+      'weight' => -10,
+      'type' => MENU_LOCAL_TASK,
+    );
+    $plugin['menu']['items']['view_subqueue'] = array(
+      'path' => 'list/%ctools_export_ui/view/%subqueue',
+      'title' => 'View',
+      'page callback' => 'ctools_export_ui_switcher_page',
+      'page arguments' => array($plugin['name'], 'view_subqueue', $prefix_count + 2, $prefix_count + 4),
+      'load arguments' => array($plugin['name']),
+      'access callback' => 'ctools_export_ui_task_access',
+      'access arguments' => array($plugin['name'], 'view_subqueue', $prefix_count + 2, $prefix_count + 4),
+      'weight' => -10,
+      'type' => MENU_CALLBACK
+    );
+    $plugin['menu']['items']['clear'] = array(
+      'path' => 'list/%ctools_export_ui/clear/%subqueue',
+      'title' => 'Clear',
+      'page callback' => 'ctools_export_ui_switcher_page',
+      'page arguments' => array($plugin['name'], 'clear', $prefix_count + 2, $prefix_count + 4),
+      'load arguments' => array($plugin['name']),
+      'access callback' => 'ctools_export_ui_task_access',
+      'access arguments' => array($plugin['name'], 'clear', $prefix_count + 2, $prefix_count + 4),
+      'type' => MENU_CALLBACK
+    );
+
+    return parent::init($plugin);
+  }
+
+  function access($op, $item) {
+    if ($op == 'list') {
+      return _nodequeue_access_admin_or_manipulate();
+    }
+    if (in_array($op, array('add', 'import', 'clone', 'revert', 'delete', 'edit')) && !user_access('administer nodequeue')) {
+      return FALSE;
+    }
+    if (in_array($op, array('view', 'clear'))) {
+      return nodequeue_queue_access($item);
+    }
+
+    return parent::access($op, $item);
+  }
+
+  /**
+   * Override add_page callback to handle queue types properly.
+   */
+  function add_page($js, $input, $type, $step = NULL) {
+    drupal_set_title($this->get_page_title('add_' . $type));
+
+    $item = nodequeue_new_queue($type);
+
+    $form_state = array(
+      'plugin' => $this->plugin,
+      'object' => &$this,
+      'ajax' => $js,
+      'item' => $item,
+      'op' => 'add',
+      'form type' => 'add',
+      'rerender' => TRUE,
+      'no_redirect' => TRUE,
+      'step' => $step,
+      // Store these in case additional args are needed.
+      'function args' => func_get_args(),
+    );
+
+    $output = $this->edit_execute_form($form_state);
+    if (!empty($form_state['executed'])) {
+      $export_key = $this->plugin['export']['key'];
+      drupal_goto(str_replace('%ctools_export_ui', $form_state['item']->{$export_key}, $this->plugin['redirect']['add']));
+    }
+
+    return $output;
+  }
+
+  /**
+   * Callback to view and manipulate a queue.
+   */
+  function view_page($js, $input, $queue) {
+    module_load_include('inc', 'nodequeue', 'includes/nodequeue.admin');
+    return nodequeue_admin_view($queue);
+  }
+
+  /**
+   * Callback to view and manipulate a subqueue.
+   */
+  function view_subqueue_page($js, $input, $queue, $subqueue) {
+    module_load_include('inc', 'nodequeue', 'includes/nodequeue.admin');
+    return nodequeue_admin_view($queue, $subqueue);
+  }
+
+
+  /**
+   * Callback to clear a queue.
+   */
+  function clear_page($js, $input, $queue, $subqueue) {
+    module_load_include('inc', 'nodequeue', 'includes/nodequeue.admin');
+    return nodequeue_clear_confirm($queue, $subqueue);
+  }
+
+}
diff --git a/plugins/nodequeue_ctools_export_ui.inc b/plugins/nodequeue_ctools_export_ui.inc
new file mode 100644
index 0000000..b26e0a3
--- /dev/null
+++ b/plugins/nodequeue_ctools_export_ui.inc
@@ -0,0 +1,308 @@
+<?php
+/**
+ * @file
+ * Define this Export UI plugin.
+ */
+
+$plugin = array(
+  'schema' => 'nodequeue_queue',
+  'access' => 'administer nodequeue',
+
+  'menu' => array(
+    'menu prefix' => 'admin/structure',
+    'menu item' => 'nodequeue',
+    'menu title' => 'Nodequeues',
+    'menu description' => 'Create and maintain simple nodequeues.',
+  ),
+
+  'allowed operations' => array(
+    'view' => array('title' => t('View')),
+  ),
+
+  'title singular' => t('queue'),
+  'title plural' => t('queues'),
+  'title singular proper' => t('Nodequeue'),
+  'title plural proper' => t('Nodequeues'),
+
+  'form' => array(
+    'settings' => 'nodequeue_ctools_export_ui_form',
+    'validate' => 'nodequeue_ctools_export_ui_form_validate',
+    'submit' => 'nodequeue_ctools_export_ui_form_submit',
+  ),
+
+  'handler' => array(
+    'class' => 'nodequeue_ctools_export_ui',
+    'parent' => 'ctools_export_ui',
+  ),
+);
+
+/**
+ * Define the nodequeue add/edit form.
+ */
+function nodequeue_ctools_export_ui_form(&$form, &$form_state) {
+  $queue = &$form_state['item'];
+
+  // Workaround a notice on the queue add page.
+  if (empty($queue->export_type)) {
+    $queue->export_type = '';
+  }
+
+  $info = nodequeue_api_info();
+
+  // For adding queues.
+  if (empty($queue->name)) {
+    $queue->new = TRUE;
+    drupal_set_title(t('Add @type', array('@type' => $info[$queue->owner]['title'])), PASS_THROUGH);
+  }
+  // For cloning queues.
+  elseif ($form_state['form type'] == 'clone') {
+    $queue->new = TRUE;
+    drupal_set_title(t('Clone @type', array('@type' => $info[$queue->owner]['title'])), PASS_THROUGH);
+  }
+  // For editing queues.
+  else {
+    $queue->new = FALSE;
+    drupal_set_title(t("Nodequeue '@title'", array('@title' => $queue->title)), PASS_THROUGH);
+  }
+
+  $form['description'] = array(
+    '#type' => 'fieldset',
+    '#title' => filter_xss($info[$queue->owner]['title']),
+    '#description' => filter_xss($info[$queue->owner]['description']),
+  );
+
+  // Improve machine name handling.
+  unset($form['info']['name']);
+  $form['info']['title'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Title'),
+    '#default_value' => $queue->title,
+    '#size' => 50,
+    '#required' => TRUE,
+    '#maxlength' => 64,
+    '#description' => t('Enter the name of the queue.'),
+    '#weight' => -1,
+  );
+  $form['info']['name'] = array(
+    '#type' => 'machine_name',
+    '#title' => t('Machine-name'),
+    '#maxlength' => 32,
+    '#machine_name' => array(
+      'exists' => 'ctools_export_ui_edit_name_exists',
+      'source' => array('info', 'title'),
+    ),
+    '#description' => t('A unique machine-readable name for this queue. It must only contain lowercase letters, numbers, and underscores.'),
+  );
+
+  // If we are editing, disable changing name.
+  if (!empty($queue->name)) {
+    $form['info']['name']['#default_value'] = $queue->name;
+    // If we're not cloning, disable editing.
+    if ($form_state['form type'] != 'clone') {
+      $form['info']['name']['#disabled'] = TRUE;
+      $form['info']['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.
+  $form['subqueue_title'] = array(
+    '#type' => 'value',
+    '#value' => $queue->subqueue_title,
+  );
+  // The placeholder is put here so that modifiers have an easy way to put
+  // additional form widgets in a prominent spot but not before the title of
+  // the queue.
+  $form['placeholder'] = array();
+
+  $form['size'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Queue size'),
+    '#default_value' => $queue->size,
+    '#size' => 2,
+    '#maxlength' => 2,
+    '#description' => t('The maximum number of nodes will appear in the queue. Enter 0 for no limit'),
+  );
+
+  $form['reverse'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Reverse in admin view'),
+    '#default_value' => $queue->reverse,
+    '#description' => t('Ordinarily queues are arranged with the front of the queue (where items will be removed) on top and the back (where items will be added) on the bottom. If checked, this will display the queue such that items will be added to the top and removed from the bottom.'),
+  );
+
+  $form['link'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Link "add to queue" text'),
+    '#default_value' => $queue->link,
+    '#size' => 40,
+    '#maxlength' => 40,
+    '#description' => t('If you want a link to add a node to a queue in the "links" section (next to "add new comment"), enter the text here. If left blank no link will be given; note that enabling this feature for any queue will cause an extra query to be run every time a node is loaded. "%subqueue" will be replaced with the subqueue title, if applicable.'),
+  );
+
+  $form['link_remove'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Link "remove from queue" text'),
+    '#default_value' => $queue->link_remove,
+    '#size' => 40,
+    '#maxlength' => 40,
+    '#description' => t('Enter the text for the corresponding link to remove a node from a queue. This may be blank (in which case no link will appear) but a remove link will only appear if link, above, is set.'),
+  );
+
+  $manipulate_all_queues = user_roles(FALSE, 'manipulate all queues');
+  $manipulate_queues = user_roles(FALSE, 'manipulate queues');
+  $roles = $manipulate_all_queues + $manipulate_queues;
+
+  if (!empty($roles)) {
+    $form['roles'] = array(
+      '#type' => 'checkboxes',
+      '#title' => t('Roles'),
+      '#default_value' => !empty($queue->roles) ? $queue->roles : array(),
+      '#options' => $roles,
+      '#description' => t('Check each role that can add nodes to the queue. Be sure that roles you want to appear here have "manipulate queues" access in the main access control panel.'),
+    );
+
+    foreach ($roles as $rid => $role) {
+      $form['roles'][$rid] = array(
+        '#type' => 'checkbox',
+        '#title' => $role,
+        '#default_value' => (isset($manipulate_all_queues[$rid]) || in_array($rid, $queue->roles)) ? TRUE : FALSE,
+        '#disabled' => (isset($manipulate_all_queues[$rid])) ? TRUE : FALSE,
+      );
+    }
+  }
+  else {
+    $form['roles'] = array(
+      '#type' => 'value',
+      '#value' => array(),
+    );
+
+    $form['roles_markup'] = array(
+      '#type' => 'item',
+      '#title' => t('Roles'),
+      '#description' => '<strong>' . t('No roles have the "manipulate queues" permission, so only the administrator account will be able to add or remove items from this queue.') . '</strong>',
+    );
+  }
+
+  $nodes = node_type_get_names();
+
+  $form['types'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Types'),
+    '#default_value' => !empty($queue->types) ? $queue->types : array(),
+    '#options' => $nodes,
+    '#description' => t('Check each node type that can be added to this queue.'),
+  );
+
+  $form['i18n'] = array(
+    '#type' => 'radios',
+    '#title' => t('Internationalization'),
+    '#options' => array(
+      '1' => t('Treat translation nodes as a single node'),
+      '0' => t('Manually manage translated nodes'),
+    ),
+    '#default_value' => $queue->new && module_exists('translation') ? 0 : (empty($queue->i18n) ? 1 : $queue->i18n),
+    '#description' => t('Treating translations as a single node allows users to add, remove and manipulate a node
+      in the queue regardless of which translation is acted upon; nodequeue will only act on the original node.
+      When manually managing translation nodes, Nodequeue will ignore the relationship between node translations;
+      each translation node must be added to the queue separately and will occupy a separate spot in the queue.
+      Changing this setting will <strong>not</strong> update content that is already in the queue.'),
+    '#access' => module_exists('translation'),
+  );
+
+  $form['owner'] = array(
+    '#type' => 'value',
+    '#value' => $queue->owner,
+  );
+
+  $form['subqueue_title'] = array(
+    '#type' => 'value',
+    '#value' => !empty($queue->subqueue_title) ? $queue->subqueue_title : '',
+  );
+
+  $form['show_in_links'] = array(
+    '#type' => 'value',
+    '#value' => $queue->show_in_links,
+  );
+
+  $form['show_in_tab'] = array(
+    '#type' => 'value',
+    '#value' => $queue->show_in_tab,
+  );
+
+  $form['show_in_ui'] = array(
+    '#type' => 'value',
+    '#value' => $queue->show_in_ui,
+  );
+
+  $form['reference'] = array(
+    '#type' => 'value',
+    '#value' => $queue->reference,
+  );
+
+  $form['subqueues'] = array(
+    '#type' => 'value',
+    '#value' => !empty($queue->subqueues) ? $queue->subqueues : array(),
+  );
+
+  // Pass this value along as this may be useful down the road.
+  $form['new'] = array(
+    '#type' => 'value',
+    '#value' => $queue->new,
+  );
+
+  // Queue_names change empty($queue->name) for proper check if existing queue.
+  if (!$queue->new) {
+    $form['count'] = array(
+      '#type' => 'value',
+      '#value' => empty($queue->count) ? 0 : $queue->count,
+    );
+  }
+
+  nodequeue_api_queue_form($queue, $form);
+
+  return $form;
+}
+
+/**
+ * Validate handler for the nodequeue edit form.
+ */
+function nodequeue_ctools_export_ui_form_validate($form, &$form_state) {
+  if (empty($form_state['values']['title'])) {
+    form_set_error('title', t('Please enter a title for this queue.'));
+  }
+  $queue = (object) $form_state['values'];
+  // Fix checkboxes.
+  $queue->roles = array_keys(array_filter($queue->roles));
+  $queue->types = array_keys(array_filter($queue->types));
+
+  nodequeue_api_queue_form_validate($queue, $form_state, $form);
+}
+
+/**
+ * Submit handler for the nodequeue edit form.
+ */
+function nodequeue_ctools_export_ui_form_submit($form, &$form_state) {
+  $queue = (object) $form_state['values'];
+  // Fix checkboxes.
+  $queue->roles = array_keys(array_filter($queue->roles));
+  $queue->types = array_keys(array_filter($queue->types));
+
+  // Remove roles that have the 'manipulate all queues' permission.
+  $manipulate_all_queues = array_keys(user_roles(FALSE, 'manipulate all queues'));
+  $queue->roles = array_diff($queue->roles, $manipulate_all_queues);
+
+  // Modify show_in_links based on whether or not links are available.
+  $queue->show_in_links = !empty($queue->link) || !empty($queue->link_remove);
+
+  nodequeue_api_queue_form_submit($queue, $form_state);
+
+  nodequeue_save($queue);
+
+  nodequeue_api_queue_form_submit_finish($queue, $form_state);
+
+  nodequeue_check_subqueue_sizes($queue);
+
+  $form_state['redirect'] = 'admin/structure/nodequeue';
+}
