Index: /extensions/bulk_manager/element_set.php
===================================================================
--- /extensions/bulk_manager/element_set.php	(revision 6771)
+++ /extensions/bulk_manager/element_set.php	(revision 6772)
@@ -44,114 +44,253 @@
 
 // +-----------------------------------------------------------------------+
-// |                    initialize info about category                     |
-// +-----------------------------------------------------------------------+
-
-if (!isset($_GET['cat']))
-{
-  $_GET['cat'] = 'caddie';
-}
-
-// To element_set_(global|unit).php, we must provide the elements id of the
-// managed category in $page['cat_elements_id'] array.
-$page['cat_elements_id'] = array();
-if (is_numeric($_GET['cat']))
-{
-  $page['title'] =
-    get_cat_display_name_from_id(
-      $_GET['cat'],
-      PHPWG_ROOT_PATH.'admin.php?page=cat_modify&amp;cat_id=',
-      false
+// |                      initialize current set                           |
+// +-----------------------------------------------------------------------+
+
+if (isset($_POST['submitFilter']))
+{
+  // echo '<pre>'; print_r($_POST); echo '</pre>';
+  
+  $_SESSION['bulk_manager_filter'] = array();
+
+  if (isset($_POST['filter_prefilter_use']))
+  {
+    $prefilters = array('caddie', 'last import', 'with no album', 'with no tag');
+    if (in_array($_POST['filter_prefilter'], $prefilters))
+    {
+      $_SESSION['bulk_manager_filter']['prefilter'] = $_POST['filter_prefilter'];
+    }    
+  }
+
+  if (isset($_POST['filter_category_use']))
+  {
+    $_SESSION['bulk_manager_filter']['category'] = $_POST['filter_category'];
+
+    if (isset($_POST['filter_category_recursive']))
+    {
+      $_SESSION['bulk_manager_filter']['category_recursive'] = true;
+    }
+  }
+
+  if (isset($_POST['filter_level_use']))
+  {
+    if (in_array($_POST['filter_level'], $conf['available_permission_levels']))
+    {
+      $_SESSION['bulk_manager_filter']['level'] = $_POST['filter_level'];
+    }
+  }
+}
+
+if (isset($_GET['cat']))
+{
+  if ('caddie' == $_GET['cat'])
+  {
+    $_SESSION['bulk_manager_filter'] = array(
+      'prefilter' => 'caddie'
       );
-
-  $query = '
-SELECT image_id
-  FROM '.IMAGE_CATEGORY_TABLE.'
-  WHERE category_id = '.$_GET['cat'].'
-;';
-  $page['cat_elements_id'] = array_from_query($query, 'image_id');
-}
-else if ('caddie' == $_GET['cat'])
-{
-  $page['title'] = l10n('caddie');
-
-  $query = '
+  }
+
+  if (is_numeric($_GET['cat']))
+  {
+    $_SESSION['bulk_manager_filter'] = array(
+      'category' => $_GET['cat']
+      );
+  }
+}
+
+if (!isset($_SESSION['bulk_manager_filter']))
+{
+  $_SESSION['bulk_manager_filter'] = array(
+    'prefilter' => 'caddie'
+    );
+}
+
+// echo '<pre>'; print_r($_SESSION['bulk_manager_filter']); echo '</pre>';
+
+// depending on the current filter (in session), we find the appropriate
+// photos
+$filter_sets = array();
+if (isset($_SESSION['bulk_manager_filter']['prefilter']))
+{
+  if ('caddie' == $_SESSION['bulk_manager_filter']['prefilter'])
+  {
+    $query = '
 SELECT element_id
   FROM '.CADDIE_TABLE.'
   WHERE user_id = '.$user['id'].'
 ;';
-  $page['cat_elements_id'] = array_from_query($query, 'element_id');
-}
-else if ('not_linked' == $_GET['cat'])
-{
-  $page['title'] = l10n('Not linked elements');
-  $template->assign(array('U_ACTIVE_MENU' => 5 ));
-
-  // we are searching elements not linked to any virtual category
+    array_push(
+      $filter_sets,
+      array_from_query($query, 'element_id')
+      );
+  }
+
+  if ('last import'== $_SESSION['bulk_manager_filter']['prefilter'])
+  {
+    $query = '
+SELECT MAX(date_available) AS date
+  FROM '.IMAGES_TABLE.'
+;';
+    $row = pwg_db_fetch_assoc(pwg_query($query));
+    if (!empty($row['date']))
+    {
+      $query = '
+SELECT id
+  FROM '.IMAGES_TABLE.'
+  WHERE date_available BETWEEN '.pwg_db_get_recent_period_expression(1, $row['date']).' AND \''.$row['date'].'\'
+;';
+      array_push(
+        $filter_sets,
+        array_from_query($query, 'id')
+        );
+    }
+  }
+}
+
+if (isset($_SESSION['bulk_manager_filter']['category']))
+{
+  $categories = array();
+  
+  if (isset($_SESSION['bulk_manager_filter']['category_recursive']))
+  {
+    $categories = get_subcat_ids(array($_SESSION['bulk_manager_filter']['category']));
+  }
+  else
+  {
+    $categories = array($_SESSION['bulk_manager_filter']['category']);
+  }
+  
+  $query = '
+ SELECT DISTINCT(image_id)
+   FROM '.IMAGE_CATEGORY_TABLE.'
+   WHERE category_id IN ('.implode(',', $categories).')
+ ;';
+  array_push(
+    $filter_sets,
+    array_from_query($query, 'image_id')
+    );
+}
+
+if (isset($_SESSION['bulk_manager_filter']['level']))
+{
   $query = '
 SELECT id
   FROM '.IMAGES_TABLE.'
+  WHERE level >= '.$_SESSION['bulk_manager_filter']['level'].'
 ;';
-  $all_elements = array_from_query($query, 'id');
-
-  $linked_to_virtual = array();
-
-  $query = '
-SELECT id
-  FROM '.CATEGORIES_TABLE.'
-  WHERE dir IS NULL
-;';
-  $virtual_categories = array_from_query($query, 'id');
-  if (!empty($virtual_categories))
-  {
-    $query = '
-SELECT DISTINCT(image_id)
-  FROM '.IMAGE_CATEGORY_TABLE.'
-  WHERE category_id IN ('.implode(',', $virtual_categories).')
-;';
-    $linked_to_virtual = array_from_query($query, 'image_id');
-  }
-
-  $page['cat_elements_id'] = array_diff($all_elements, $linked_to_virtual);
-}
-else if ('duplicates' == $_GET['cat'])
-{
-  $page['title'] = l10n('Files with same name in more than one physical category');
-  $template->assign(array('U_ACTIVE_MENU' => 5 ));
-
-  // we are searching related elements twice or more to physical categories
-  // 1 - Retrieve Files
-  $query = '
-SELECT DISTINCT(file)
-  FROM '.IMAGES_TABLE.'
- GROUP BY file
-HAVING COUNT(DISTINCT storage_category_id) > 1
-;';
-
-  $duplicate_files = array_from_query($query, 'file');
-  $duplicate_files[]='Nofiles';
-  // 2 - Retrives related picture ids
-  $query = '
-SELECT id, file
-  FROM '.IMAGES_TABLE.'
-WHERE file IN (\''.implode("','", $duplicate_files).'\')
-ORDER BY file, id
-;';
-
-  $page['cat_elements_id'] = array_from_query($query, 'id');
-}
-elseif ('recent'== $_GET['cat'])
-{
-  $page['title'] = l10n('Recent pictures');
-  $query = 'SELECT MAX(date_available) AS date
-  FROM '.IMAGES_TABLE;
-  $row = pwg_db_fetch_assoc(pwg_query($query));
-  if (!empty($row['date']))
-  {
-    $query = 'SELECT id
-  FROM '.IMAGES_TABLE.'
-  WHERE date_available BETWEEN '.pwg_db_get_recent_period_expression(1, $row['date']).' AND \''.$row['date'].'\'';
-    $page['cat_elements_id'] = array_from_query($query, 'id');
-  }
-}
+  array_push(
+    $filter_sets,
+    array_from_query($query, 'id')
+    );
+}
+
+$current_set = array_shift($filter_sets);
+foreach ($filter_sets as $set)
+{
+  $current_set = array_intersect($current_set, $set);
+}
+$page['cat_elements_id'] = $current_set;
+
+//  // To element_set_(global|unit).php, we must provide the elements id of the
+//  // managed category in $page['cat_elements_id'] array.
+//  $page['cat_elements_id'] = array();
+//  if (is_numeric($_GET['cat']))
+//  {
+//    $page['title'] =
+//      get_cat_display_name_from_id(
+//        $_GET['cat'],
+//        PHPWG_ROOT_PATH.'admin.php?page=cat_modify&amp;cat_id=',
+//        false
+//        );
+//  
+//    $query = '
+//  SELECT image_id
+//    FROM '.IMAGE_CATEGORY_TABLE.'
+//    WHERE category_id = '.$_GET['cat'].'
+//  ;';
+//    $page['cat_elements_id'] = array_from_query($query, 'image_id');
+//  }
+//  else if ('caddie' == $_GET['cat'])
+//  {
+//    $page['title'] = l10n('caddie');
+//  
+//    $query = '
+//  SELECT element_id
+//    FROM '.CADDIE_TABLE.'
+//    WHERE user_id = '.$user['id'].'
+//  ;';
+//    $page['cat_elements_id'] = array_from_query($query, 'element_id');
+//  }
+//  else if ('not_linked' == $_GET['cat'])
+//  {
+//    $page['title'] = l10n('Not linked elements');
+//    $template->assign(array('U_ACTIVE_MENU' => 5 ));
+//  
+//    // we are searching elements not linked to any virtual category
+//    $query = '
+//  SELECT id
+//    FROM '.IMAGES_TABLE.'
+//  ;';
+//    $all_elements = array_from_query($query, 'id');
+//  
+//    $linked_to_virtual = array();
+//  
+//    $query = '
+//  SELECT id
+//    FROM '.CATEGORIES_TABLE.'
+//    WHERE dir IS NULL
+//  ;';
+//    $virtual_categories = array_from_query($query, 'id');
+//    if (!empty($virtual_categories))
+//    {
+//      $query = '
+//  SELECT DISTINCT(image_id)
+//    FROM '.IMAGE_CATEGORY_TABLE.'
+//    WHERE category_id IN ('.implode(',', $virtual_categories).')
+//  ;';
+//      $linked_to_virtual = array_from_query($query, 'image_id');
+//    }
+//  
+//    $page['cat_elements_id'] = array_diff($all_elements, $linked_to_virtual);
+//  }
+//  else if ('duplicates' == $_GET['cat'])
+//  {
+//    $page['title'] = l10n('Files with same name in more than one physical category');
+//    $template->assign(array('U_ACTIVE_MENU' => 5 ));
+//  
+//    // we are searching related elements twice or more to physical categories
+//    // 1 - Retrieve Files
+//    $query = '
+//  SELECT DISTINCT(file)
+//    FROM '.IMAGES_TABLE.'
+//   GROUP BY file
+//  HAVING COUNT(DISTINCT storage_category_id) > 1
+//  ;';
+//  
+//    $duplicate_files = array_from_query($query, 'file');
+//    $duplicate_files[]='Nofiles';
+//    // 2 - Retrives related picture ids
+//    $query = '
+//  SELECT id, file
+//    FROM '.IMAGES_TABLE.'
+//  WHERE file IN (\''.implode("','", $duplicate_files).'\')
+//  ORDER BY file, id
+//  ;';
+//  
+//    $page['cat_elements_id'] = array_from_query($query, 'id');
+//  }
+//  elseif ('recent'== $_GET['cat'])
+//  {
+//    $page['title'] = l10n('Recent pictures');
+//    $query = 'SELECT MAX(date_available) AS date
+//    FROM '.IMAGES_TABLE;
+//    $row = pwg_db_fetch_assoc(pwg_query($query));
+//    if (!empty($row['date']))
+//    {
+//      $query = 'SELECT id
+//    FROM '.IMAGES_TABLE.'
+//    WHERE date_available BETWEEN '.pwg_db_get_recent_period_expression(1, $row['date']).' AND \''.$row['date'].'\'';
+//      $page['cat_elements_id'] = array_from_query($query, 'id');
+//    }
+//  }
 
 // +-----------------------------------------------------------------------+
Index: /extensions/bulk_manager/element_set_global.php
===================================================================
--- /extensions/bulk_manager/element_set_global.php	(revision 6771)
+++ /extensions/bulk_manager/element_set_global.php	(revision 6772)
@@ -325,8 +325,8 @@
 $template->assign(
   array(
+    'filter' => $_SESSION['bulk_manager_filter'],
+    
     'selection' => $collection,
     
-    'CATEGORIES_NAV'=>$page['title'],
-
     'U_DISPLAY'=>$base_url.get_query_string_diff(array('display')),
 
@@ -337,5 +337,5 @@
     .'&amp;mode=unit',
 
-    'F_ACTION'=>$base_url.get_query_string_diff(array()),
+    'F_ACTION'=>$base_url.get_query_string_diff(array('cat')),
    )
  );
@@ -345,5 +345,11 @@
 // +-----------------------------------------------------------------------+
 
-$template->assign('IN_CADDIE', 'caddie' == $_GET['cat'] ? true : false );
+$in_caddie = false;
+if (isset($_SESSION['bulk_manager_filter']['prefilter'])
+    and 'caddie' == $_SESSION['bulk_manager_filter']['prefilter'])
+{
+  $in_caddie = true;
+}
+$template->assign('IN_CADDIE', $in_caddie);
 
 // +-----------------------------------------------------------------------+
@@ -375,4 +381,14 @@
 // +-----------------------------------------------------------------------+
 
+// privacy level
+$template->assign(
+    array(
+      'filter_level_options'=> get_privacy_level_options(),
+      'filter_level_options_selected' => isset($_SESSION['bulk_manager_filter']['level'])
+        ? $_SESSION['bulk_manager_filter']['level']
+        : 0,
+    )
+  );
+
 // Virtualy associate a picture to a category
 $query = '
@@ -381,4 +397,41 @@
 ;';
 display_select_cat_wrapper($query, array(), 'associate_options', true);
+
+// in the filter box, which category to select by default
+$selected_category = array();
+
+if (isset($_SESSION['bulk_manager_filter']['category']))
+{
+  $selected_category = array($_SESSION['bulk_manager_filter']['category']);
+}
+else
+{
+  // we need to know the category in which the last photo was added
+  $selected_category = array();
+
+  $query = '
+SELECT
+    category_id,
+    id_uppercat
+  FROM '.IMAGES_TABLE.' AS i
+    JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON image_id = i.id
+    JOIN '.CATEGORIES_TABLE.' AS c ON category_id = c.id
+  ORDER BY i.id DESC
+  LIMIT 1
+;';
+  $result = pwg_query($query);
+  if (pwg_db_num_rows($result) > 0)
+  {
+    $row = pwg_db_fetch_assoc($result);
+  
+    $selected_category = array($row['category_id']);
+  }
+}
+
+$query = '
+SELECT id,name,uppercats,global_rank
+  FROM '.CATEGORIES_TABLE.'
+;';
+display_select_cat_wrapper($query, $selected_category, 'filter_category_options', true);
 
 // Dissociate from a category : categories listed for dissociation can
Index: /extensions/bulk_manager/element_set_global.tpl
===================================================================
--- /extensions/bulk_manager/element_set_global.tpl	(revision 6771)
+++ /extensions/bulk_manager/element_set_global.tpl	(revision 6772)
@@ -235,4 +235,47 @@
   });
 
+  $(".removeFilter").click(function () {
+    var filter = $(this).parent('li').attr("id");
+    filter_disable(filter);
+
+    return false;
+  });
+
+  function filter_enable(filter) {
+    /* show the filter*/
+    $("#"+filter).show();
+
+    /* check the checkbox to declare we use this filter */
+    $("input[type=checkbox][name="+filter+"_use]").attr("checked", true);
+
+    /* forbid to select this filter in the addFilter list */
+    $("#addFilter").children("option[value="+filter+"]").attr("disabled", "disabled");
+  }
+
+  $("#addFilter").change(function () {
+    var filter = $(this).attr("value");
+    filter_enable(filter);
+    $(this).attr("value", -1);
+  });
+
+  function filter_disable(filter) {
+    /* hide the filter line */
+    $("#"+filter).hide();
+
+    /* uncheck the checkbox to declare we do not use this filter */
+    $("input[name="+filter+"_use]").removeAttr("checked");
+
+    /* give the possibility to show it again */
+    $("#addFilter").children("option[value="+filter+"]").removeAttr("disabled");
+  }
+
+  $("#removeFilters").click(function() {
+    $("#filterList li").each(function() {
+      var filter = $(this).attr("id");
+      filter_disable(filter);
+    });
+    return false;
+  });
+
   checkPermitAction()
 });
@@ -253,40 +296,82 @@
 #selectSet a {border-bottom:1px dotted}
 #applyOnDetails {font-style:italic;}
+
+.actionButtons {text-align:left;}
+#filterList {padding-left:5px;}
+#filterList li {margin-bottom:5px; list-style-type:none;}
+a.removeFilter {background: url(plugins/bulk_manager/remove_filter.png) no-repeat top left;width:7px;height:7px;display:inline-block}
+a.removeFilter:hover {background: url(plugins/bulk_manager/remove_filter_hover.png); border:none;}
+.removeFilter span {display:none}
+#applyFilterBlock {margin-top:20px;}
+.useFilterCheckbox {display:none}
 </style>
 {/literal}
 
+  <p style="float:left; font-size:90%;margin:5px 0 0 0;padding:0;">
+    <a href="{$U_UNIT_MODE}">Switch to unit mode</a>
+  </p>
+
 <h2>{'Batch management'|@translate}</h2>
 
-<h3>{$CATEGORIES_NAV}</h3>
-
-{if !empty($thumbnails)}
-  <p style="text-align:center;">
-    {'global mode'|@translate}
-    | <a href="{$U_UNIT_MODE}">{'unit mode'|@translate}</a>
-  </p>
-
-  <fieldset style="display:none;">
-
-    <legend>{'Display options'|@translate}</legend>
-
-    <p>{'elements per page'|@translate}:
-        <a href="{$U_DISPLAY}&amp;display=20">20</a>
-      | <a href="{$U_DISPLAY}&amp;display=50">50</a>
-      | <a href="{$U_DISPLAY}&amp;display=100">100</a>
-      | <a href="{$U_DISPLAY}&amp;display=all">{'all'|@translate}</a>
+  <form action="{$F_ACTION}" method="post">
+
+  <fieldset>
+    <legend>{'Filter'|@translate}</legend>
+
+    <ul id="filterList">
+      <li id="filter_prefilter" {if !isset($filter.prefilter)}style="display:none"{/if}>
+        <a href="#" class="removeFilter" title="remove this filter"><span>[x]</span></a>
+        <input type="checkbox" name="filter_prefilter_use" class="useFilterCheckbox" {if isset($filter.prefilter)}checked="checked"{/if}>
+        predefined filter
+        <select name="filter_prefilter">
+          <option value="caddie" {if $filter.prefilter eq 'caddie'}selected="selected"{/if}>caddie</option>
+          <option value="last import" {if $filter.prefilter eq 'last import'}selected="selected"{/if}>last import</option>
+<!--          <option value="with no album">with no album</option> -->
+<!--          <option value="with no virtual album">with no virtual album</option> -->
+<!--          <option value="with no tag">with no tag</option> -->
+        </select>
+      </li>
+      <li id="filter_category" {if !isset($filter.category)}style="display:none"{/if}>
+        <a href="#" class="removeFilter" title="remove this filter"><span>[x]</span></a>
+        <input type="checkbox" name="filter_category_use" class="useFilterCheckbox" {if isset($filter.category)}checked="checked"{/if}>
+        album
+        <select style="width:400px" name="filter_category" size="1">
+          {html_options options=$filter_category_options selected=$filter_category_options_selected}
+        </select>
+        <label><input type="checkbox" name="filter_category_recursive" {if isset($filter.category_recursive)}checked="checked"{/if}> {'include child albums'|@translate}</label>
+      </li>
+      <li id="filter_level" {if !isset($filter.level)}style="display:none"{/if}>
+        <a href="#" class="removeFilter" title="remove this filter"><span>[x]</span></a>
+        <input type="checkbox" name="filter_level_use" class="useFilterCheckbox" {if isset($filter.level)}checked="checked"{/if}>
+        {'Who can see these photos?'|@translate}
+        <select name="filter_level" size="1">
+          {html_options options=$filter_level_options selected=$filter_level_options_selected}
+        </select>
+      </li>
+    </ul>
+
+    <p class="actionButtons" style="">
+      <select id="addFilter">
+        <option value="-1">Add a filter</option>
+        <option disabled="disabled">------------------</option>
+        <option value="filter_prefilter">predefined filter</option>
+        <option value="filter_category">album</option>
+        <option value="filter_level">{'Who can see these photos?'|@translate}</option>
+      </select>
+<!--      <input id="removeFilters" class="submit" type="submit" value="Remove all filters" name="removeFilters"> -->
+      <a id="removeFilters" href="">Remove all filters</a>
     </p>
 
+    <p class="actionButtons" id="applyFilterBlock">
+      <input id="applyFilter" class="submit" type="submit" value="Refresh photo set" name="submitFilter">
+    </p>
+
   </fieldset>
 
-<!--  <fieldset> -->
-<!--    <legend>{'Filter'|@translate}</legend> -->
-<!--  </fieldset> -->
-
-  <form action="{$F_ACTION}" method="post">
-
   <fieldset>
 
     <legend>{'Selection'|@translate}</legend>
 
+  {if !empty($thumbnails)}
   <p id="checkActions">
     {'Select:'|@translate}
@@ -304,5 +389,4 @@
   </p>
 
-  {if !empty($thumbnails)}
     <ul class="thumbnails">
       {foreach from=$thumbnails item=thumbnail}
@@ -332,5 +416,4 @@
       {/foreach}
     </ul>
-  {/if}
 
   {if !empty($navbar) }
@@ -351,4 +434,7 @@
   {/if}
 
+  {else}
+  <div>No photo in the current set.</div>
+  {/if}
   </fieldset>
 
@@ -462,5 +548,5 @@
     </div>
 
-    <p id="applyActionBlock" style="display:none">
+    <p id="applyActionBlock" style="display:none" class="actionButtons">
       <input id="applyAction" class="submit" type="submit" value="{'Apply action'|@translate}" name="submit" {$TAG_INPUT_ENABLED}> <span id="applyOnDetails"></span></p>
 
@@ -469,6 +555,2 @@
 
   </form>
-
-{else}
-  <div class="infos"><p>{'Caddie is currently empty'|@translate}</p></div>
-{/if}
Index: /extensions/bulk_manager/main.inc.php
===================================================================
--- /extensions/bulk_manager/main.inc.php	(revision 6771)
+++ /extensions/bulk_manager/main.inc.php	(revision 6772)
@@ -2,5 +2,5 @@
 /*
 Plugin Name: Bulk Manager
-Version: auto
+Version: 2.1a
 Description: Bulk Manager new generation, for Piwigo 2.2
 Plugin URI: http://piwigo.org/ext/extension_view.php?eid=440
