diff --git a/includes/subscribe.inc b/includes/subscribe.inc
index 703114b..c90d893 100644
--- a/includes/subscribe.inc
+++ b/includes/subscribe.inc
@@ -1,172 +1,183 @@
 <?php
 
-function project_issue_subscribe($form_state, $project_nid = 0) {
-  global $user;
+/**
+ * Returns project issue subscription levels.
+ */
+function _project_issue_subscription_levels() {
+  return array(
+    0 => t('None'),
+    1 => t('Flagged issues'),
+    2 => t('All issues'),
+  );
+}
 
-  if (!valid_email_address($user->mail)) {
-    drupal_set_message(t('You need to provide a valid e-mail address to subscribe to issue e-mails. Please edit your user information.'), 'error');
-    drupal_goto('user/'. $user->uid .'/edit');
+/**
+ * Form constructor for global user project issue subscriptions.
+ */
+function project_issue_user_subscribe_form(&$form_state, $account) {
+  // Global subscription level.
+  $level = db_result(db_query("SELECT level FROM {project_user_subscriptions} WHERE uid = %d", array($account->uid)));
+  // Default to None.
+  if (!$level) {
+    $level = 0;
   }
+  $form['uid'] = array(
+    '#type' => 'value',
+    '#value' => $account->uid,
+  );
+  $form['level'] = array(
+    '#type' => 'radios',
+    '#title' => t('Global project issue subscription level'),
+    '#options' => _project_issue_subscription_levels(),
+    '#default_value' => $level,
+  );
 
-  $levels = array(0 => t('None'), 1 => t('Own issues'), 2 => t('All issues'));
-
-  if ($project_nid) {
-    if (!is_numeric($project_nid)) {
-      $project_nid = db_result(db_query(db_rewrite_sql("SELECT p.nid FROM {project_projects} p WHERE p.uri = '%s'", 'p'), $project_nid));
-    }
-    if (!$project_nid) {
-      return drupal_not_found();
-    }
-
-    $project = node_load($project_nid);
-    project_project_set_breadcrumb($project, TRUE);
-
-    $level = db_result(db_query('SELECT level FROM {project_subscriptions} WHERE nid = %d AND uid = %d', $project->nid, $user->uid));
-    $form['single'] = array(
-      '#type' => 'value',
-      '#value' => $project->nid,
-    );
-    $form['#project'] = array(
-      '#type' => 'value',
-      '#value' => $project,
-    );
-    $form['subscribe'] = array(
-      '#type' => 'markup',
-      '#value' => '<p>'. t('Subscribe to receive e-mail notification when an issue for this project is updated.') .'</p>',
+  // Per-project subscription level (only enabled).
+  // We only allow to change (and remove) per-project subscriptions on this
+  // form. Users are able to subscribe to further projects by visiting the
+  // individual project pages. In terms of UX, that's preferred anyway, since
+  // a user normally wants to know and be sure what exactly she subscribes to.
+  $form['projects'] = array(
+    '#tree' => TRUE,
+    '#theme' => 'project_issue_user_subscribe_project_table',
+    '#header' => array(t('Project'), t('Subscription level')),
+    '#description' => t('Per-project subscriptions having the same or a lower level than the global level will be removed.'),
+  );
+  $result = db_query(db_rewrite_sql("SELECT s.nid, n.title, s.level
+    FROM {project_subscriptions} s
+    INNER JOIN {node} n ON n.nid = s.nid
+    WHERE n.type = 'project_project' AND n.status = 1 AND s.uid = %d ORDER BY n.title
+    ", 's'), $account->uid);
+  while ($project = db_fetch_object($result)) {
+    $form['projects'][$project->nid]['title'] = array(
+      '#value' => l($project->title, "node/$project->nid"),
     );
-    $form['options']['#tree'] = TRUE;
-    $form['options'][$project->nid] = array(
-      '#type' => 'radios',
-      '#title' => t('Subscribe to @project issues', array('@project' => $project->title)),
-      '#default_value' => isset($level) ? $level : 0,
-      '#options' => $levels,
+    $form['projects'][$project->nid]['level'] = array(
+      '#type' => 'select',
+      '#options' => $form['level']['#options'],
     );
-
   }
-  else {
 
-    $form['buttons']['all'] = array(
-      '#type' => 'markup',
-      '#value' => t('All projects'),
-    );
-    foreach ($levels as $key => $level) {
-      $form['buttons'][$level] = array(
-        '#type' => 'submit',
-        '#name' => 'all',
-        '#value' => $level,
-      );
-    }
-    $nids = array();
-
-    $result = db_query(db_rewrite_sql("SELECT s.nid, n.title, s.level, p.uri FROM {project_subscriptions} s INNER JOIN {node} n ON n.nid = s.nid INNER JOIN {project_projects} p ON n.nid = p.nid WHERE n.type = 'project_project' AND n.status = 1 AND s.uid = %d ORDER BY n.title", 's'), $user->uid);
-    while ($project = db_fetch_object($result)) {
-      $form['project'][$project->nid]['title'] = array(
-        '#value' => l($project->title, "node/$project->nid"),
-      );
-      foreach ($levels as $key => $level) {
-        if ($project->level == $key) {
-          $status[$project->nid] = $key;
-        }
-      }
-      $nids[] = $project->nid;
-    }
-
-    if (empty($nids)) {
-      $placeholders = '';
-    }
-    else {
-      $placeholders = " AND n.nid NOT IN (". implode(',', array_fill(0, count($nids), '%d')) .")";
-    }
-
-    $result = db_query(db_rewrite_sql("SELECT n.nid, n.title, p.uri FROM {node} n INNER JOIN {project_projects} p ON n.nid = p.nid WHERE n.type = 'project_project' AND n.status = 1". ($nids ?  $placeholders : "") ." ORDER BY n.title"), $nids);
-    while ($project = db_fetch_object($result)) {
-      $form['project'][$project->nid]['title'] = array(
-        '#value' => l($project->title, "node/$project->nid"),
-      );
-      $nids[] = $project->nid;
-    }
-
-    foreach ($nids as $nid) {
-      $form['options']['#tree'] = TRUE;
-      $form['options'][$nid] = array(
-        '#type' => 'radios',
-        '#default_value' => isset($status[$nid]) ? $status[$nid] : 0,
-        '#options' => $levels,
-      );
-    }
-  }
-  $form['submit'] = array(
+  $form['actions']['submit'] = array(
     '#type' => 'submit',
-    '#value' => t('Subscribe'),
+    '#value' => t('Save'),
   );
   return $form;
 }
 
-function theme_project_issue_subscribe($form) {
-  global $user;
+/**
+ * Form submission handler for project_issue_user_subscribe_form().
+ */
+function project_issue_user_subscribe_form_submit($form, &$form_state) {
+  // Delete the existing global setting.
+  db_query("DELETE FROM {project_user_subscriptions} WHERE uid = %d", array($form_state['values']['uid']));
+
+  // Insert the new global setting.
+  // There is no need to keep record for the global "None" setting.
+  if ($form_state['values']['level']) {
+    db_query("INSERT INTO {project_user_subscriptions} (uid, level) VALUES (%d, %d)", array($form_state['values']['uid'], $form_state['values']['level']));
+  }
 
-  $output = '';
+  // Delete the existing per-project settings.
+  db_query("DELETE FROM {project_subscriptions} WHERE uid = %d", array($form_state['values']['uid']));
 
-  if (empty($form['#project'])) {
-    $output .= project_issue_query_result_links();
-  }
-  else {
-    $project = $form['#project']['#value'];
-    $output .= project_issue_query_result_links($project->project['uri']);
+  // Insert the new per-project settings.
+  foreach ($form_state['values']['projects'] as $nid => $level) {
+    // Skip all per-project settings having the same or a lower level than the
+    // global default.
+    if ($level > $form_state['values']['level']) {
+      db_query("INSERT INTO {project_subscriptions} (nid, uid, level) VALUES (%d, %d, %d)", array($form_state['values']['nid'], $form_state['values']['uid'], $level));
+    }
   }
 
-  if (!isset($form['single'])) {
-    $levels = array(0 => t('None'), 1 => t('Own issues'), 2 => t('All issues'));
-    $headers = array_merge(array(t('Project')), $levels);
+  drupal_set_message(t('Your subscriptions have been updated.'));
+}
 
+/**
+ * Returns HTML for per-project subscription levels table in project_issue_user_subscribe_form().
+ */
+function theme_project_issue_user_subscribe_project_table($element) {
+  $output = '';
+  $rows = array();
+  foreach (element_children($element) as $nid) {
     $row = array();
-    foreach (element_children($form['buttons']) as $key) {
-      $row[] = drupal_render($form['buttons'][$key]);
-    }
-    $rows = array($row);
-
-    foreach (element_children($form['project']) as $key) {
-      $row = array(drupal_render($form['project'][$key]['title']));
-      foreach ($levels as $level => $name) {
-        $row[] = drupal_render($form['options'][$key][$level]);
-      }
-      $rows[] = $row;
-    }
-    $output .= theme('table', $headers, $rows);
+    $row[] = drupal_render($element[$nid]['title']);
+    $row[] = drupal_render($element[$nid]['level']);
+    $rows[] = array();
+  }
+  if (!empty($rows)) {
+    $output .= theme('table', $element['#header'], $rows);
+    $output .= check_plain($element['#description']);
   }
 
-  $output .= drupal_render($form);
+  $output .= drupal_render($element);
   return $output;
 }
 
-function project_issue_subscribe_submit($form, &$form_state) {
-
+/**
+ * Form constructor for per-project issue subscription.
+ */
+function project_issue_project_subscribe_form($form_state, $project_nid) {
   global $user;
-  $all = $form_state['clicked_button']['#value'];
 
-  $levels = array(0 => t('None'), 1 => t('Own issues'), 2 => t('All issues'));
+  // @todo Isn't this globally enforced elsewhere...?
+  if (!valid_email_address($user->mail)) {
+    drupal_set_message(t('You need to provide a valid e-mail address to subscribe to issue e-mails. Please edit your user information.'), 'error');
+    drupal_goto('user/'. $user->uid .'/edit');
+  }
 
-    // Remove previous subscriptions for user.
-    if (isset($form_state['values']['single'])) {
-      db_query('DELETE FROM {project_subscriptions} WHERE nid = %d AND uid = %d', $form_state['values']['single'], $user->uid);
-    }
-    else {
-      db_query('DELETE FROM {project_subscriptions} WHERE uid = %d', $user->uid);
-    }
+  if (!is_numeric($project_nid)) {
+    $project_nid = db_result(db_query(db_rewrite_sql("SELECT p.nid FROM {project_projects} p WHERE p.uri = '%s'", 'p'), $project_nid));
+  }
+  $project = node_load($project_nid);
+  if (!$project) {
+    return drupal_not_found();
+  }
 
-    $_level = array_search($all, $levels);
+  project_project_set_breadcrumb($project, TRUE);
+  drupal_set_title(t('Subscribe to @project issues', array('@project' => $project->title)));
 
-    foreach ($form_state['values']['options'] as $nid => $level) {
-      if ($_level !== 0 && $level !== 0) {
-        db_query('INSERT INTO {project_subscriptions} (nid, uid, level) VALUES (%d, %d, %d)', $nid, $user->uid, $_level ? $_level : $level);
-      }
-    }
-    drupal_set_message(t('Subscription settings saved.'));
+  $form['#project'] = $project;
+  $form['nid'] = array(
+    '#type' => 'value',
+    '#value' => $project->nid,
+  );
+  $form['uid'] = array(
+    '#type' => 'value',
+    '#value' => $user->uid,
+  );
 
-    if (isset($form['single'])) {
-      $form_state['redirect'] = 'project/issues/subscribe-mail/'. $form['#project']['#value']->project['uri'];
-    }
-    else {
-      $form_state['redirect'] = 'project/issues/subscribe-mail';
-    }
+  $level = db_result(db_query('SELECT level FROM {project_subscriptions} WHERE nid = %d AND uid = %d', $project->nid, $user->uid));
+  // Default to None.
+  if (!$level) {
+    $level = 0;
+  }
+  $form['level'] = array(
+    '#type' => 'radios',
+    '#title' => t('Subscription level'),
+    '#options' => _project_issue_subscription_levels(),
+    '#default_value' => $level,
+    '#description' => t('Receive an e-mail notification when an issue for this project is updated.'),
+  );
+
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Subscribe'),
+  );
+  return $form;
+}
+
+/**
+ * Form submission handler for project_issue_user_subscribe_form().
+ */
+function project_issue_project_subscribe_form_submit($form, &$form_state) {
+  // Delete the existing per-project setting.
+  db_query("DELETE FROM {project_subscriptions} WHERE nid = %d AND uid = %d", array($form_state['values']['nid'], $form_state['values']['uid']));
+
+  // Insert the new per-project setting.
+  if ($form_state['values']['level']) {
+    db_query("INSERT INTO {project_subscriptions} (nid, uid, level) VALUES (%d, %d, %d)", array($form_state['values']['nid'], $form_state['values']['uid'], $form_state['values']['level']));
+  }
+
+  drupal_set_message(t('Your subscription setting has been updated.'));
 }
diff --git a/project_issue.install b/project_issue.install
index 1c24aff..85efe2b 100644
--- a/project_issue.install
+++ b/project_issue.install
@@ -282,6 +282,28 @@ function project_issue_schema() {
     'primary key' => array('priority'),
   );
 
+  $schema['project_user_subscriptions'] = array(
+    'description' => 'Stores global issue subscriptions per user.',
+    'fields' => array(
+      'uid' => array(
+        'description' => 'The {users}.uid for this subscriber.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'level' => array(
+        'description' => 'The global subscription setting level. 0 = None, 1 = Flagged, 2 = All.',
+        'type' => 'int',
+        'size' => 'tiny',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'primary key' => array('uid', 'level'),
+  );
+
   $schema['project_subscriptions'] = array(
     'description' => 'Table keeping track of per-user project_issue subscriptions.',
     'fields' => array(
@@ -626,3 +648,38 @@ function project_issue_update_6006() {
 
   return $ret;
 }
+
+function project_issue_update_6007() {
+  $ret = array();
+
+  // Delete obsolete 'project_issue_global_subscribe_page' variable.
+  variable_del('project_issue_global_subscribe_page');
+
+  // Create new global issue subscription setting table.
+  db_create_table($ret, 'project_user_subscriptions', array(
+    'description' => 'Stores global issue subscriptions per user.',
+    'fields' => array(
+      'uid' => array(
+        'description' => 'The {users}.uid for this subscriber.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'level' => array(
+        'description' => 'The global subscription setting level. 0 = None, 1 = Flagged, 2 = All.',
+        'type' => 'int',
+        'size' => 'tiny',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'primary key' => array('uid', 'level'),
+  ));
+
+  // Ensure that existing project subscriptions are clean.
+  $ret[] = update_sql("DELETE FROM {project_subscriptions} WHERE level = 0");
+
+  return $ret;
+}
diff --git a/project_issue.module b/project_issue.module
index 4345d1d..e8a5c00 100644
--- a/project_issue.module
+++ b/project_issue.module
@@ -61,20 +61,25 @@ function project_issue_menu() {
     'type' => MENU_NORMAL_ITEM,
     'file' => 'includes/statistics.inc',
   );
-  $path = 'project/issues/subscribe-mail';
-  if (!variable_get('project_issue_global_subscribe_page', TRUE)) {
-    // If we don't want the global subscribe page, require an argument.
-    $path .= '/%';
-  }
-  $items[$path] = array(
+
+  $items['project/issues/subscribe-mail/%'] = array(
     'title' => 'Subscribe',
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('project_issue_subscribe', 3),
+    'page arguments' => array('project_issue_project_subscribe_form', 3),
     'access callback' => 'project_issue_menu_access',
     'access arguments' => array('auth'),
     'type' => MENU_NORMAL_ITEM,
     'file' => 'includes/subscribe.inc',
   );
+  $items['user/%user/subscribe-mail'] = array(
+    'title' => 'Subscribe',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('project_issue_user_subscribe_form', 1),
+    'access callback' => 'project_issue_menu_access',
+    'access arguments' => array('auth'),
+    'file' => 'includes/subscribe.inc',
+  );
+
   if (module_exists('search')) {
     $items['search/issues'] = array(
       'title' => 'Issues',
@@ -1834,13 +1839,6 @@ function project_issue_query_result_links($project_arg = NULL) {
         'attributes' => array('title' => t('See statistics about issues.')),
       );
     }
-    if (!empty($user->uid) && variable_get('project_issue_global_subscribe_page', TRUE)) {
-      $links['subscribe'] = array(
-        'title' => t('Subscribe'),
-        'href' => "project/issues/subscribe-mail",
-        'attributes' => array('title' => t('Receive e-mail updates about issues.')),
-      );
-    }
   }
   else {
     // We know the project, make project-specific links.
