diff -Nuar standard_moodle/lib/listlib.php my_moodle/lib/listlib.php
--- standard_moodle/lib/listlib.php	2011-03-07 22:11:38.000000000 +0300
+++ my_moodle/lib/listlib.php	2011-03-07 22:16:32.000000000 +0300
@@ -64,8 +64,24 @@
 
     public $editable;
 
-    /** @var array keys are child ids, values are parents. */
-    public $childparent;
+    /**
+     * Key is child id, value is parent.
+     * @var array
+     * Cache of all items contained in list
+     * Presents only in top-level list
+     * @var array that contains from:
+     * [id]['sortorder'] => sortorder
+     * [id]['parent'] => parentid
+     * [id]['item'] => reference to item object
+     */
+    public $itemscache = null;
+
+    /**
+     * Used to get $itemscache
+     * @var reference to top-level list
+     */
+    var $toplevellist = null;
+
 
 //------------------------------------------------------
 //vars used for pagination.
@@ -89,8 +105,9 @@
      * @param integer $page if 0 no pagination. (These three params only used in top level list.)
      * @param string $pageparamname name of url param that is used for passing page no
      * @param integer $itemsperpage no of top level items.
+     * @param reference to the top-level list that contained $itemscache
      */
-    public function __construct($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20) {
+    public function __construct($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20, $toplevellist = null) {
         global $PAGE;
 
         $this->editable = $editable;
@@ -105,6 +122,49 @@
         } else {
             $this->pageurl = $pageurl;
         }
+        if ($toplevellist === null) {
+            $this->toplevellist = $this;
+            $this->toplevellist->itemscache = array();
+        } else {
+            $this->toplevellist = $toplevellist;
+        }
+    }
+
+    /**
+     * Returns state of list: moving or not
+     * @return bool state
+     */
+    function is_moving_active() {
+        global $USER;
+        $paramname = get_class($this).'moving';
+        return isset($USER->$paramname);
+    }
+    /**
+     * Change move state
+     * @param ineger $mode id of item to move or 0 to stop moving
+     */
+    function set_moving_item($mode) {
+        global $USER;
+        $paramname = get_class($this).'moving';
+        if ($mode>0) {
+            $USER->$paramname = $mode;
+        } else {
+            unset($USER->$paramname);
+        }
+    }
+
+    /**
+     * Returns id of item to move
+     * @return integer id of item to move or 0
+     */
+    function get_moving_item() {
+        global $USER;
+        if ($this->is_moving_active()) {
+            $paramname = get_class($this).'moving';
+            return $USER->$paramname;
+        } else {
+            return 0;
+        }
     }
 
     /**
@@ -113,6 +173,7 @@
      * @param integer $indent depth of indentation.
      */
     public function to_html($indent=0, $extraargs=array()) {
+        global $CFG;
         if (count($this->items)) {
             $tabs = str_repeat("\t", $indent);
             $first = true;
@@ -121,15 +182,36 @@
             $html = '';
 
             foreach ($this->items as $item) {
+                // ignoring  item which ig going to be moved
+                if ($this->get_moving_item() == $item->id) {
+                    continue;
+                }
                 $last = (count($this->items) == $itemiter);
                 if ($this->editable) {
                     $item->set_icon_html($first, $last, $lastitem);
                 }
+                // inserting "movebefore" action in the beginnig of the top-level list
+                if ($this->is_moving_active() && $first && !isset($this->parentitem)) {
+                    $action = array('actionname'=>'movebefore','actionargs'=>$item->id, 'sesskey' => sesskey());
+                    $html .= '<li' . (!empty($item->attributes) ? " {$item->attributes}" : '') . '>';
+                    $html .= "<a href=\"{$this->pageurl->out(true, $action)}\">";
+                    $html .= "<img class=\"movetarget\" src=\"{$CFG->wwwroot}/pix/movehere.gif\" alt=\"movehere\" />";
+                    $html .= "</a></li>\n";
+                }
+                // generating HTML-code of an item
                 if ($itemhtml = $item->to_html($indent+1, $extraargs)) {
                     $html .= "$tabs\t<li".((!empty($item->attributes))?(' '.$item->attributes):'').">";
                     $html .= $itemhtml;
                     $html .= "</li>\n";
                 }
+                // inserting "moveafter" action after every list item
+                if ($this->is_moving_active()) {
+                    $action = array('actionname'=>'moveafter','actionargs'=>$item->id, 'sesskey' => sesskey());
+                    $html .= '<li' . (!empty($item->attributes) ? " {$item->attributes}" : '') . '>';
+                    $html .= "<a href=\"{$this->pageurl->out(true, $action)}\">";
+                    $html .= "<img class=\"movetarget\" src=\"{$CFG->wwwroot}/pix/movehere.gif\" alt=\"movehere\" />";
+                    $html .= "</a></li>\n";
+                }
                 $first = false;
                 $lastitem = $item;
                 $itemiter++;
@@ -206,15 +288,16 @@
             $this->lastitem = $this->firstitem + $this->itemsperpage - 1;
         }
         $itemiter = $offset;
-        //make a simple array which is easier to search
-        $this->childparent = array();
         foreach ($records as $record) {
-            $this->childparent[$record->id] = $record->parent;
+            // Caching items to prevent a lot of database queries in future
+            $this->toplevellist->itemscache[$record->id] = array();
+            $this->toplevellist->itemscache[$record->id]['sortorder'] = $record->sortorder;
+            $this->toplevellist->itemscache[$record->id]['parent'] = $record->parent;
         }
 
         //create top level list items and they're responsible for creating their children
         foreach ($records as $record) {
-            if (array_key_exists($record->parent, $this->childparent)) {
+            if (array_key_exists($record->parent, $this->toplevellist->itemscache)) {
                 // This record is a child of another record, so it will be dealt
                 // with by a call to list_item::create_children, not here.
                 continue;
@@ -233,7 +316,7 @@
             $this->items[$itemiter] = new $this->listitemclassname($record, $this, $newattributes, $inpage);
 
             if ($inpage) {
-                $this->items[$itemiter]->create_children($records, $this->childparent, $record->id);
+                $this->items[$itemiter]->create_children($records, $this->toplevellist->itemscache, $record->id);
             } else {
                 // Don't recurse down the tree for items that are not on this page
                 $this->paged = true;
@@ -274,7 +357,7 @@
 
     /**
      * Returns an array of ids of peers of an item.
-     *
+     * @deprecated should be deleted with process_actions
      * @param    int itemid - if given, restrict records to those with this parent id.
      * @return   array peer ids
      */
@@ -299,7 +382,7 @@
 
     /**
      * Move a record up or down
-     *
+     * @deprecated should be deleted with process_actions
      * @param string $direction up / down
      * @param integer $id
      */
@@ -330,6 +413,9 @@
         $this->reorder_peers($peers);
     }
 
+    /**
+     * @deprecated should be deleted with process_actions
+     */
     public function reorder_peers($peers) {
         global $DB;
         foreach ($peers as $key => $peer) {
@@ -338,6 +424,7 @@
     }
 
     /**
+      * @deprecated should be deleted with process_actions
      * @param integer $id an item index.
      * @return object the item that used to be the parent of the item moved.
      */
@@ -364,7 +451,7 @@
 
     /**
      * Make item with id $id the child of the peer that is just above it in the sort order.
-     *
+     * @deprecated should be deleted with process_actions
      * @param integer $id
      */
     public function move_item_right($id) {
@@ -389,7 +476,7 @@
 
     /**
      * process any actions.
-     *
+     * @deprecated use process_action instead
      * @param integer $left id of item to move left
      * @param integer $right id of item to move right
      * @param integer $moveup id of item to move up
@@ -437,6 +524,70 @@
     }
 
     /**
+     * Process any action
+     * @param string $action name of action. Can be: startmove, cancelmove,
+     * movebefore, moveafter, movefirstchild
+     * @param integer $value id of item
+     */
+    function process_action($action,$value) {
+        global $DB;
+        if ($action=='movebefore' || $action=='moveafter' || $action=='movefirstchild') {
+            $itemtomove = $this->toplevellist->itemscache[$this->get_moving_item()];
+            $itemtomove['id'] = $this->get_moving_item();
+            $anchor = $this->toplevellist->itemscache[$value];
+            $anchor['id'] = $value;
+        }
+
+        switch ($action){
+            case 'startmove': // pushed "Move" button
+                $this->set_moving_item($value);
+                break;
+            case 'cancelmove': // pushed "Cancel" button
+                $this->set_moving_item(0);
+                break;
+            case 'movebefore': // use this to move in the beginning of the group
+                $extendsparameters = array($anchor['parent']);
+                $extendsortorders = "UPDATE {{$this->table}} SET sortorder = sortorder + 1 WHERE parent = ?";
+                $moveparameters = array($anchor['parent'], $itemtomove['id']);
+                $move = "UPDATE {{$this->table}} SET parent = ?, sortorder = 0 WHERE id = ?";
+                $reduceparameters = array($itemtomove['parent'], $itemtomove['sortorder']);
+                $reducesortorders = "UPDATE {{$this->table}} SET sortorder = sortorder - 1 WHERE parent = ? AND sortorder > ?";
+                $DB->execute($extendsortorders, $extendsparameters);
+                $DB->execute($move, $moveparameters);
+                $DB->execute($reducesortorders, $reduceparameters);
+                $this->set_moving_item(0);
+                break;
+            case 'moveafter': // move item after selected item
+                $extendsparameters = array($anchor['parent'], $anchor['sortorder']);
+                $extendsortorders = "UPDATE {{$this->table}} SET sortorder = sortorder + 1 WHERE parent = ? AND sortorder > ?";
+                $moveparameters = array($anchor['parent'], $anchor['sortorder'] + 1,$itemtomove['id']);
+                $move = "UPDATE {{$this->table}} SET parent = ?, sortorder = ? WHERE id = ?";
+                $reduceparameters = array($itemtomove['parent'], $itemtomove['sortorder']);
+                $reducesortorders = "UPDATE {{$this->table}} SET sortorder = sortorder - 1 WHERE parent = ? AND sortorder > ?";
+                $DB->execute($extendsortorders, $extendsparameters);
+                $DB->execute($move, $moveparameters);
+                $DB->execute($reducesortorders, $reduceparameters);
+                $this->set_moving_item(0);
+                break;
+            case 'movefirstchild': // insert list item as subitem
+                $extendsparameters = array($anchor['id']);
+                $extendsortorders = "UPDATE {{$this->table}} SET sortorder = sortorder + 1 WHERE parent = ?";
+                $moveparameters = array($anchor['id'], $itemtomove['id']);
+                $move = "UPDATE {{$this->table}} SET parent = ?, sortorder = 0 WHERE id = ?";
+                $reduceparameters = array($itemtomove['parent'], $itemtomove['sortorder']);
+                $reducesortorders = "UPDATE {{$this->table}} SET sortorder = sortorder - 1 WHERE parent = ? AND sortorder > ?";
+                $DB->execute($extendsortorders, $extendsparameters);
+                $DB->execute($move, $moveparameters);
+                $DB->execute($reducesortorders, $reduceparameters);
+                $this->set_moving_item(0);
+                break;
+            default:
+                return false;
+        }
+        redirect($this->pageurl->out());
+    }
+
+    /**
      * @param integer $itemid an item id.
      * @return boolean Is the item with the given id the first top-level item on
      * the current page?
@@ -529,58 +680,43 @@
      * @return string html
      */
     public function to_html($indent = 0, $extraargs = array()) {
+        global $CFG;
         if (!$this->display) {
             return '';
         }
         $tabs = str_repeat("\t", $indent);
 
+        // inserting "movefirstchild" action in the beginning of every list
+        if ($this->parentlist->is_moving_active()) {
+            $action = array('actionname' => 'movefirstchild', 'actionargs' => $this->id, 'sesskey' => sesskey());
+            $childrenhtml .= '<ul><li' . (!empty($this->attributes) ? " {$this->attributes}" : '') . '>';
+            $childrenhtml .= "<a href=\"{$this->parentlist->pageurl->out(true, $action)}\">";
+            $childrenhtml .= "<img class=\"movetarget\" src=\"{$CFG->wwwroot}/pix/movehere.gif\" alt=\"movehere\" />";
+            $childrenhtml .= "</li></ul>\n";
+        }
+
         if (isset($this->children)) {
-            $childrenhtml = $this->children->to_html($indent+1, $extraargs);
-        } else {
-            $childrenhtml = '';
+            $childrenhtml .= $this->children->to_html($indent+1, $extraargs);
         }
         return $this->item_html($extraargs).'&nbsp;'.(join($this->icons, '')).(($childrenhtml !='')?("\n".$childrenhtml):'');
     }
 
     public function set_icon_html($first, $last, $lastitem) {
-        global $CFG;
-        $strmoveup = get_string('moveup');
-        $strmovedown = get_string('movedown');
-        $strmoveleft = get_string('maketoplevelitem', 'question');
-
-        if (isset($this->parentlist->parentitem)) {
-            $parentitem = $this->parentlist->parentitem;
-            if (isset($parentitem->parentlist->parentitem)) {
-                $action = get_string('makechildof', 'question', $parentitem->parentlist->parentitem->name);
+        $strmove = get_string('move');
+        $action = array(
+                'actionname' => 'startmove',
+                'actionargs' => $this->id,
+                'sesskey'  => sesskey());
+        $iconurl = $this->parentlist->pageurl->out(true, $action);
+        if (!$this->parentlist->is_moving_active()) {
+            // "Move"-icon must be drawn in all list-items except alone item in list
+            if (!isset($this->parentlist->parentitem)) {
+                if (count($this->parentlist->items)>1) {
+                    $this->icons['move'] = $this->image_icon($strmove, $iconurl, 'move');
+                }
             } else {
-                $action = $strmoveleft;
+                $this->icons['move'] =  $this->image_icon($strmove, $iconurl, 'move');
             }
-            $url = new moodle_url($this->parentlist->pageurl, (array('sesskey'=>sesskey(), 'left'=>$this->id)));
-            $this->icons['left'] = $this->image_icon($action, $url, 'left');
-        } else {
-            $this->icons['left'] =  $this->image_spacer();
-        }
-
-        if (!$first) {
-            $url = new moodle_url($this->parentlist->pageurl, (array('sesskey'=>sesskey(), 'moveup'=>$this->id)));
-            $this->icons['up'] = $this->image_icon($strmoveup, $url, 'up');
-        } else {
-            $this->icons['up'] =  $this->image_spacer();
-        }
-
-        if (!$last) {
-            $url = new moodle_url($this->parentlist->pageurl, (array('sesskey'=>sesskey(), 'movedown'=>$this->id)));
-            $this->icons['down'] = $this->image_icon($strmovedown, $url, 'down');
-        } else {
-            $this->icons['down'] =  $this->image_spacer();
-        }
-
-        if (!empty($lastitem)) {
-            $makechildof = get_string('makechildof', 'question', $lastitem->name);
-            $url = new moodle_url($this->parentlist->pageurl, (array('sesskey'=>sesskey(), 'right'=>$this->id)));
-            $this->icons['right'] = $this->image_icon($makechildof, $url, 'right');
-        } else {
-            $this->icons['right'] =  $this->image_spacer();
         }
     }
 
@@ -603,8 +739,13 @@
      * @param integer $thisrecordid
      */
     public function create_children(&$records, &$children, $thisrecordid) {
-        //keys where value is $thisrecordid
-        $thischildren = array_keys($children, $thisrecordid);
+        //keys where parent is $thisrecordid
+        $children[$thisrecordid]['item'] = $this;
+        $thischildren = array();
+        foreach($children as $id => $item) {
+            if ($item['parent'] == $thisrecordid)
+                $thischildren[]= $id;
+        }
         foreach ($thischildren as $child) {
             $thisclass = get_class($this);
             $newlistitem = new $thisclass($records[$child], $this->children, $this->attributes);
diff -Nuar standard_moodle/question/category_class.php my_moodle/question/category_class.php
--- standard_moodle/question/category_class.php	2011-03-07 22:11:39.000000000 +0300
+++ my_moodle/question/category_class.php	2011-03-08 21:27:46.000000000 +0300
@@ -29,34 +29,68 @@
     public $context = null;
     public $sortby = 'parent, sortorder, name';
 
-    public function __construct($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20, $context = null){
-        parent::__construct('ul', '', $editable, $pageurl, $page, 'cpage', $itemsperpage);
+    public function __construct($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20, $context = null, $toplevellist = null){
+        parent::__construct('ul', '', $editable, $pageurl, $page, 'cpage', $itemsperpage, $toplevellist);
         $this->context = $context;
     }
 
+    function list_from_records($paged = false, $offset = 0) {
+        $result = parent::list_from_records($paged, $offset);
+        foreach ($this->records as $record) {
+            // context will used for moving items between contexts
+            $this->toplevellist->itemscache[$record->id]['context'] = $this->context->id;
+        }
+        return $result;
+    }
+
     public function get_records() {
         $this->records = get_categories_for_contexts($this->context->id, $this->sortby);
     }
+
+    /**
+     * Returns array that contains id's of all element which ares childs of this list
+     * @return array which contains id's if all child elements
+     */
+    function get_child_ids_recursive() {
+        $childs = array();
+        if (isset($this->items)) {
+            foreach ($this->items as $child) {
+                $childs[] = $child->id;
+                $recurs = $child->children->get_child_ids_recursive();
+                $childs = array_merge($childs, $recurs);
+            }
+        }
+        return $childs;
+    }
+
+    function process_action($action, $value) {
+        global $DB;
+        if (($action == 'movefirstchild' || $action == 'moveafter' || $action == 'movebefore') 
+                // Changing context if item to move and anchor item are in defferent contexts
+                && $this->toplevellist->itemscache[$this->get_moving_item()]['context'] != $this->toplevellist->itemscache[$value]['context']) {
+            global $CFG;
+            $itemstorecontext = $this->toplevellist->itemscache[$this->get_moving_item()]['item']->children->get_child_ids_recursive();
+            $itemstorecontext[] = $this->get_moving_item();
+            $contextid = $this->toplevellist->itemscache[$value]['context'];
+            $itemstorecontext = $DB->get_in_or_equal($itemstorecontext);
+            $query = "UPDATE {{$this->table}} SET contextid = ? WHERE id {$itemstorecontext[0]}";
+            $itemstorecontext = array_merge(array($contextid), $itemstorecontext[1]);
+            $DB->execute($query, $itemstorecontext);
+        }
+        // parent::process_action redirects after any action
+        parent::process_action($action, $value);
+    }
 }
 
 class question_category_list_item extends list_item {
     public function set_icon_html($first, $last, &$lastitem){
         global $CFG;
-        $category = $this->item;
-        $url = new moodle_url('/question/category.php', ($this->parentlist->pageurl->params() + array('edit'=>$category->id)));
-        $this->icons['edit']= $this->image_icon(get_string('editthiscategory', 'question'), $url, 'edit');
-        parent::set_icon_html($first, $last, $lastitem);
-        $toplevel = ($this->parentlist->parentitem === null);//this is a top level item
-        if (($this->parentlist->nextlist !== null) && $last && $toplevel && (count($this->parentlist->items)>1)){
-            $url = new moodle_url($this->parentlist->pageurl, array('movedowncontext'=>$this->id, 'tocontext'=>$this->parentlist->nextlist->context->id, 'sesskey'=>sesskey()));
-            $this->icons['down'] = $this->image_icon(
-                get_string('shareincontext', 'question', print_context_name($this->parentlist->nextlist->context)), $url, 'down');
-        }
-        if (($this->parentlist->lastlist !== null) && $first && $toplevel && (count($this->parentlist->items)>1)){
-            $url = new moodle_url($this->parentlist->pageurl, array('moveupcontext'=>$this->id, 'tocontext'=>$this->parentlist->lastlist->context->id, 'sesskey'=>sesskey()));
-            $this->icons['up'] = $this->image_icon(
-                get_string('shareincontext', 'question', print_context_name($this->parentlist->lastlist->context)), $url, 'up');
+        if (!$this->parentlist->is_moving_active()) {
+            $category = $this->item;
+            $url = new moodle_url('/question/category.php', $this->parentlist->pageurl->params() + array('edit' => $category->id));
+            $this->icons['edit']= $this->image_icon(get_string('editthiscategory', 'question'), $url, 'edit');
         }
+        parent::set_icon_html($first, $last, $lastitem);
     }
 
     public function item_html($extraargs = array()){
@@ -74,7 +108,7 @@
         $item .= '&nbsp;'. $category->info;
 
         // don't allow delete if this is the last category in this context.
-        if (count($this->parentlist->records) != 1) {
+        if (count($this->parentlist->records) != 1 && !$this->parentlist->is_moving_active()) {
             $item .=  '<a title="' . $str->delete . '" href="'.$this->parentlist->pageurl->out(true, array('delete'=>$this->id, 'sesskey'=>sesskey())).'">
                     <img src="' . $OUTPUT->pix_url('t/delete') . '" class="iconsmall" alt="' .$str->delete. '" /></a>';
         }
@@ -112,6 +146,18 @@
     var $catform;
 
     /**
+     * Cache of all items contained in list
+     * Presents only in top-level list.
+     * For question category list top-level list is question_category_object
+     * @var array that contains from:
+     * [id]['sortorder'] => sortorder
+     * [id]['parent'] => parentid
+     * [id]['item'] => reference to item object
+     * [id]['context'] => question category context
+     */
+    var $itemscache = null;
+
+    /**
      * Constructor
      *
      * Gets necessary strings and sets relevant path information
@@ -127,8 +173,6 @@
         $this->str->questions      = get_string('questions', 'quiz');
         $this->str->add            = get_string('add');
         $this->str->delete         = get_string('delete');
-        $this->str->moveup         = get_string('moveup');
-        $this->str->movedown       = get_string('movedown');
         $this->str->edit           = get_string('editthiscategory', 'question');
         $this->str->hide           = get_string('hide');
         $this->str->publish        = get_string('publish', 'quiz');
@@ -156,8 +200,9 @@
      */
     public function initialize($page, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts) {
         $lastlist = null;
+        $this->itemcache = array();
         foreach ($contexts as $context){
-            $this->editlists[$context->id] = new question_category_list('ul', '', true, $this->pageurl, $page, 'cpage', QUESTION_PAGE_LENGTH, $context);
+            $this->editlists[$context->id] = new question_category_list('ul', '', true, $this->pageurl, $page, 'cpage', QUESTION_PAGE_LENGTH, $context, $this);
             $this->editlists[$context->id]->lastlist =& $lastlist;
             if ($lastlist!== null){
                 $lastlist->nextlist =& $this->editlists[$context->id];
@@ -175,6 +220,21 @@
             $this->catform->set_data(array('parent'=>$defaultcategory));
         }
     }
+
+    /**
+     * Handles question category list actions
+     * @param string $action action name
+     * @param string $value action argument
+     */
+    function process_action($action, $value) {
+        if ($action != 'noaction') {
+            global $USER;
+            confirm_sesskey();
+            $context = $this->itemscache[$value]['context'];
+            $this->editlists[$context]->process_action($action, $value);
+        }
+    }
+
     /**
      * Displays the user interface
      *
@@ -200,6 +260,26 @@
     }
 
     /**
+     * Outputs a link to cancel moving category
+     */
+    function print_cancel_moving_link() {
+        global $COURSE,$USER;
+        $itemtomove = 0;
+        if (count($this->editlists)>0){
+            reset($this->editlists);
+            $itemtomove = current($this->editlists)->get_moving_item();
+        }
+
+        if ($itemtomove != 0) {
+            $itemname = $this->itemscache[$itemtomove]['item']->name;
+            echo "<p align='center'>" . get_string('movingcategory','question') .
+                 ": {$itemname} (<a href='category.php?actionname=cancelmove" .
+                 "&actionargs={$itemtomove}&sesskey={$USER->sesskey}&courseid=" .
+                 "{$COURSE->id}'>" . get_string('cancel') . '</a>)</p>';
+        }
+    }
+
+    /**
      * Outputs a list to allow editing/rearranging of existing categories
      *
      * $this->initialize() must have already been called
@@ -209,6 +289,7 @@
         global $OUTPUT;
 
         echo $OUTPUT->heading_with_help(get_string('editcategories', 'question'), 'editcategories', 'question');
+        $this->print_cancel_moving_link();
 
         foreach ($this->editlists as $context => $list){
             $listhtml = $list->to_html(0, array('str'=>$this->str));
@@ -360,7 +441,14 @@
         $cat->contextid = $contextid;
         $cat->name = $newcategory;
         $cat->info = $newinfo;
-        $cat->sortorder = 999;
+        // There are shouldn't be two items in one list with the same sortorder
+        $cat->sortorder = 0;
+        $neighbors = $this->itemscache[$cat->parent]['item']->children->items;
+        foreach ($neighbors as $item) {
+            if ($item->item->sortorder>=$cat->sortorder)
+                $cat->sortorder = $item->item->sortorder + 1;
+        }
+
         $cat->stamp = make_unique_id_code();
         $categoryid = $DB->insert_record("question_categories", $cat);
         if ($return) {
@@ -385,6 +473,13 @@
 
         if (!empty($newparent) && !$lastcategoryinthiscontext) {
             list($parentid, $tocontextid) = explode(',', $newparent);
+            // If parent changed category will moved in the end of list
+            $newsortorder = 0;
+            $neighbors = $this->itemscache[$parentid]['item']->children->items;
+            foreach ($neighbors as $item) {
+                if ($item->item->sortorder>=$newsortorder)
+                    $newsortorder = $item->item->sortorder + 1;
+            }
         } else {
             $parentid = $oldcat->parent;
             $tocontextid = $oldcat->contextid;
@@ -407,6 +502,7 @@
         $cat->info = $newinfo;
         $cat->parent = $parentid;
         $cat->contextid = $tocontextid;
+        $cat->sortorder = $newsortorder;
         $DB->update_record('question_categories', $cat);
 
         // If the category name has changed, rename any random questions in that category.
diff -Nuar standard_moodle/question/category.php my_moodle/question/category.php
--- standard_moodle/question/category.php	2011-03-07 22:11:39.000000000 +0300
+++ my_moodle/question/category.php	2011-03-03 22:13:13.000000000 +0300
@@ -17,18 +17,10 @@
 
     // get values from form for actions on this page
     $param = new stdClass();
-    $param->moveup = optional_param('moveup', 0, PARAM_INT);
-    $param->movedown = optional_param('movedown', 0, PARAM_INT);
-    $param->moveupcontext = optional_param('moveupcontext', 0, PARAM_INT);
-    $param->movedowncontext = optional_param('movedowncontext', 0, PARAM_INT);
-    $param->tocontext = optional_param('tocontext', 0, PARAM_INT);
-    $param->left = optional_param('left', 0, PARAM_INT);
-    $param->right = optional_param('right', 0, PARAM_INT);
     $param->delete = optional_param('delete', 0, PARAM_INT);
     $param->confirm = optional_param('confirm', 0, PARAM_INT);
-    $param->cancel = optional_param('cancel', '', PARAM_ALPHA);
-    $param->move = optional_param('move', 0, PARAM_INT);
-    $param->moveto = optional_param('moveto', 0, PARAM_INT);
+    $param->actionname = optional_param('actionname', 'noaction', PARAM_ALPHA);
+    $param->actionargs = optional_param('actionargs', 0, PARAM_INT);
     $param->edit = optional_param('edit', 0, PARAM_INT);
 
     $url = new moodle_url($thispageurl);
@@ -44,14 +36,7 @@
                                 $contexts->having_cap('moodle/question:add'));
 
     $streditingcategories = get_string('editcategories', 'quiz');
-    if ($param->left || $param->right || $param->moveup || $param->movedown|| $param->moveupcontext || $param->movedowncontext){
-        require_sesskey();
-        foreach ($qcobject->editlists as $list){
-            //processing of these actions is handled in the method where appropriate and page redirects.
-            $list->process_actions($param->left, $param->right, $param->moveup, $param->movedown,
-                                    $param->moveupcontext, $param->movedowncontext, $param->tocontext);
-        }
-    }
+    $qcobject->process_action($param->actionname, $param->actionargs);
     if ($param->delete && ($questionstomove = $DB->count_records("question", array("category" => $param->delete)))){
         if (!$category = $DB->get_record("question_categories", array("id" => $param->delete))) {  // security
             print_error('nocate', 'question', $thispageurl->out(), $param->delete);
