diff --git a/grade/edit/tree/grade.php b/grade/edit/tree/grade.php
index 93b1410ea7d..8bceae84cc2 100644
--- a/grade/edit/tree/grade.php
+++ b/grade/edit/tree/grade.php
@@ -51,7 +51,7 @@ if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$courseid)
 }
 
 // now verify grading user has access to all groups or is member of the same group when separate groups used in course
-if (groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
+if (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
     if ($groups = groups_get_all_groups($COURSE->id, $userid)) {
         $ok = false;
         foreach ($groups as $group) {
diff --git a/grade/export/ods/index.php b/grade/export/ods/index.php
index 50794d69199..8eb17b5a789 100755
--- a/grade/export/ods/index.php
+++ b/grade/export/ods/index.php
@@ -51,7 +51,7 @@ $mform = new grade_export_form(null, array('publishing' => true));
 
 // process post information
 if ($data = $mform->get_data()) {
-    $export = new grade_export_ods($course, get_current_group($course->id));
+    $export = new grade_export_ods($course, groups_get_course_group($course));
 
     // print the grades on screen for feedbacks
     $export->process_form($data);
@@ -60,7 +60,8 @@ if ($data = $mform->get_data()) {
     die;
 }
 
-//TODO: add course group selector here
+groups_print_course_menu($course, 'index.php?id='.$id);
+echo '<div class="clearer"></div>';
 
 $mform->display();
 
diff --git a/grade/export/txt/index.php b/grade/export/txt/index.php
index 3921ff58eab..39c71e214f5 100755
--- a/grade/export/txt/index.php
+++ b/grade/export/txt/index.php
@@ -51,7 +51,7 @@ $mform = new grade_export_form(null, array('includeseparator'=>true, 'publishing
 
 // process post information
 if ($data = $mform->get_data()) {
-    $export = new grade_export_txt($course, get_current_group($course->id));
+    $export = new grade_export_txt($course, groups_get_course_group($course));
 
     // print the grades on screen for feedbacks
     $export->process_form($data);
@@ -60,7 +60,8 @@ if ($data = $mform->get_data()) {
     die;
 }
 
-//TODO: add course group selector here
+groups_print_course_menu($course, 'index.php?id='.$id);
+echo '<div class="clearer"></div>';
 
 $mform->display();
 
diff --git a/grade/export/xls/index.php b/grade/export/xls/index.php
index 3c37637ca72..1c0af0eeaca 100755
--- a/grade/export/xls/index.php
+++ b/grade/export/xls/index.php
@@ -51,7 +51,7 @@ $mform = new grade_export_form(null, array('publishing' => true));
 
 // process post information
 if ($data = $mform->get_data()) {
-    $export = new grade_export_xls($course, get_current_group($course->id));
+    $export = new grade_export_xls($course, groups_get_course_group($course));
 
     // print the grades on screen for feedbacks
     $export->process_form($data);
@@ -60,7 +60,8 @@ if ($data = $mform->get_data()) {
     die;
 }
 
-//TODO: add course group selector here
+groups_print_course_menu($course, 'index.php?id='.$id);
+echo '<div class="clearer"></div>';
 
 $mform->display();
 
diff --git a/grade/export/xml/index.php b/grade/export/xml/index.php
index bc12d8fd61d..1036f97d3c8 100755
--- a/grade/export/xml/index.php
+++ b/grade/export/xml/index.php
@@ -51,7 +51,7 @@ $mform = new grade_export_form(null, array('idnumberrequired'=>true, 'publishing
 
 // process post information
 if ($data = $mform->get_data()) {
-    $export = new grade_export_xml($course, get_current_group($course->id));
+    $export = new grade_export_xml($course, groups_get_course_group($course));
 
     // print the grades on screen for feedbacks
     $export->process_form($data);
@@ -60,7 +60,8 @@ if ($data = $mform->get_data()) {
     die;
 }
 
-//TODO: add course group selector here
+groups_print_course_menu($course, 'index.php?id='.$id);
+echo '<div class="clearer"></div>';
 
 $mform->display();
 
diff --git a/grade/report/lib.php b/grade/report/lib.php
index 0700b722c4d..a73366d5444 100755
--- a/grade/report/lib.php
+++ b/grade/report/lib.php
@@ -18,6 +18,12 @@ class grade_report {
      */
     var $courseid;
 
+    /**
+     * The course.
+     * @var object $course
+     */
+    var $course;
+
     /** Grade plugin return tracking object.
     var $gpr;
 
@@ -104,9 +110,15 @@ class grade_report {
      * @param int $page The current page being viewed (when report is paged)
      */
     function grade_report($courseid, $gpr, $context, $page=null) {
-        global $CFG;
+        global $CFG, $COURSE;
 
         $this->courseid  = $courseid;
+        if ($this->courseid == $COURSE->id) {
+            $this->course = $COURSE;
+        } else {
+            $this->course = get_record('course', 'id', $this->courseid);
+        }
+        
         $this->gpr       = $gpr;
         $this->context   = $context;
         $this->page      = $page;
@@ -273,15 +285,8 @@ class grade_report {
         global $CFG;
 
         /// find out current groups mode
-        $course = get_record('course', 'id', $this->courseid);
-        $groupmode = $course->groupmode;
-        ob_start();
-        $this->currentgroup = setup_and_print_groups($course, $groupmode, $this->pbarurl);
-        $this->group_selector = ob_get_clean();
-
-        // update paging after group
-        $this->baseurl .= 'group='.$this->currentgroup.'&amp;';
-        $this->pbarurl .= 'group='.$this->currentgroup.'&amp;';
+        $this->group_selector = groups_print_course_menu($this->course, $this->pbarurl, true);
+        $this->currentgroup = groups_get_course_group($this->course);
 
         if ($this->currentgroup) {
             $this->groupsql = " LEFT JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id ";
@@ -312,7 +317,7 @@ class grade_report {
      * @return string HTML
      */
     function get_module_link($modulename, $itemmodule=null, $iteminstance=null) {
-        global $CFG, $COURSE;
+        global $CFG;
 
         $link = null;
         if (!is_null($itemmodule) AND !is_null($iteminstance)) {
@@ -322,7 +327,7 @@ class grade_report {
                             . '/icon.gif" class="icon activity" alt="' . $modulename . '" />' . $modulename;
             }
 
-            $coursemodule = get_coursemodule_from_instance($itemmodule, $iteminstance, $COURSE->id);
+            $coursemodule = get_coursemodule_from_instance($itemmodule, $iteminstance, $this->course->id);
 
             $dir = $CFG->dirroot . "/mod/$itemmodule/";
             $url = $CFG->wwwroot . "/mod/$itemmodule/";
diff --git a/lib/grouplib.php b/lib/grouplib.php
index 935e07eb3a4..af2aab37777 100644
--- a/lib/grouplib.php
+++ b/lib/grouplib.php
@@ -208,6 +208,14 @@ function groups_get_grouping_members($groupingid, $fields='u.*', $sort='lastname
                           ORDER BY $sort");
 }
 
+/**
+ * Returns effective groupmode used in course
+ * @return integer group mode
+ */
+function groups_get_course_groupmode($course) {
+    return $course->groupmode;
+}
+
 /**
  * Returns effective groupmode used in activity, course setting
  * overrides activity setting if groupmodeforce enabled.
@@ -228,6 +236,66 @@ function groups_get_activity_groupmode($cm) {
     return empty($course->groupmodeforce) ? $cm->groupmode : $course->groupmode;
 }
 
+/**
+ * Print group menu selector for course level.
+ * @param object $course course object
+ * @param string $urlroot return address
+ * @param boolean $return return as string instead of printing
+ * @return mixed void or string depending on $return param
+ */
+function groups_print_course_menu($course, $urlroot, $return=false) {
+    global $CFG, $USER;
+
+    if (!$groupmode = $course->groupmode) {
+        if ($return) {
+            return '';
+        } else {
+            return;
+        }
+    }
+
+    $context = get_context_instance(CONTEXT_COURSE, $course->id);
+    if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
+        $allowedgroups = groups_get_all_groups($course->id, 0);
+    } else {
+        $allowedgroups = groups_get_all_groups($course->id, $USER->id);
+    }
+
+    $activegroup = groups_get_course_group($course, true);
+
+    $groupsmenu = array();
+    if (!$allowedgroups or $groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
+        $groupsmenu[0] = get_string('allparticipants');
+    }
+
+    if ($allowedgroups) {
+        foreach ($allowedgroups as $group) {
+            $groupsmenu[$group->id] = format_string($group->name);
+        }
+    }
+
+    if ($groupmode == VISIBLEGROUPS) {
+        $grouplabel = get_string('groupsvisible');
+    } else {
+        $grouplabel = get_string('groupsseparate');
+    }
+
+    if (count($groupsmenu) == 1) {
+        $groupname = reset($groupsmenu);
+        $output = $grouplabel.': '.$groupname;
+    } else {
+        $output = popup_form($urlroot.'&amp;group=', $groupsmenu, 'selectgroup', $activegroup, '', '', '', true, 'self', $grouplabel);
+    }
+
+    $output = '<div class="groupselector">'.$output.'</div>';
+
+    if ($return) {
+        return $output;
+    } else {
+        echo $output;
+    }
+}
+
 /**
  * Print group menu selector for activity.
  * @param object $cm course module object
@@ -293,6 +361,69 @@ function groups_print_activity_menu($cm, $urlroot, $return=false) {
     }
 }
 
+/**
+ * Returns group active in course, changes the group by default if 'group' page param present
+ *
+ * @param object $course course bject
+ * @param boolean $update change active group if group param submitted
+ * @return mixed false if groups not used, int if groups used, 0 means all groups (access must be verified in SEPARATE mode)
+ */
+function groups_get_course_group($course, $update=false) {
+    global $CFG, $USER, $SESSION;
+
+    if (!$groupmode = $course->groupmode) {
+        // NOGROUPS used
+        return false;
+    }
+
+    // init activegroup array
+    if (!array_key_exists('activegroup', $SESSION)) {
+        $SESSION->activegroup = array();
+    }
+    if (!array_key_exists($course->id, $SESSION->activegroup)) {
+        $SESSION->activegroup[$course->id] = array(SEPARATEGROUPS=>array(), VISIBLEGROUPS=>array());
+    }
+
+    // grouping used the first time - add first user group as default
+    if (!array_key_exists(0, $SESSION->activegroup[$course->id][$groupmode])) {
+        if ($usergroups = groups_get_all_groups($course->id, $USER->id, 0)) {
+            $fistgroup = reset($usergroups);
+            $SESSION->activegroup[$course->id][$groupmode][0] = $fistgroup->id;
+        } else {
+            // this happen when user not assigned into group in SEPARATEGROUPS mode or groups do not exist yet
+            // mod authors must add extra checks for this when SEPARATEGROUPS mode used (such as when posting to forum)
+            $SESSION->activegroup[$course->id][$groupmode][0] = 0;
+        }
+    }
+
+    // set new active group if requested
+    $changegroup = optional_param('group', -1, PARAM_INT);
+    if ($update and $changegroup != -1) {
+        $context = get_context_instance(CONTEXT_COURSE, $course->id);
+
+        if ($changegroup == 0) {
+            // do not allow changing to all groups without accessallgroups capability
+            if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
+                $SESSION->activegroup[$course->id][$groupmode][0] = 0;
+            }
+
+        } else {
+            // first make list of allowed groups
+            if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
+                $allowedgroups = groups_get_all_groups($course->id, 0, 0);
+            } else {
+                $allowedgroups = groups_get_all_groups($course->id, $USER->id, 0);
+            }
+
+            if ($allowedgroups and array_key_exists($changegroup, $allowedgroups)) {
+                $SESSION->activegroup[$course->id][$groupmode][0] = $changegroup;
+            }
+        }
+    }
+
+    return $SESSION->activegroup[$course->id][$groupmode][0];
+}
+
 /**
  * Returns group active in activity, changes the group by default if 'group' page param present
  *
@@ -313,7 +444,7 @@ function groups_get_activity_group($cm, $update=false) {
         return false;
     }
 
-    // innit activegroup array
+    // init activegroup array
     if (!array_key_exists('activegroup', $SESSION)) {
         $SESSION->activegroup = array();
     }