diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 4fba8cf..6419414 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -6479,54 +6479,86 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
         return;
     }
 
-    QWidget *fp = first->focusProxy();
-    if (fp) {
+    QWidget *fpx = first->focusProxy();
+    QWidget *f_end = 0;
+    if (fpx) {
         // If first is redirected, set first to the last child of first
         // that can take keyboard focus so that second is inserted after
         // that last child, and the focus order within first is (more
         // likely to be) preserved.
         QList<QWidget *> l = qFindChildren<QWidget *>(first);
-        for (int i = l.size()-1; i >= 0; --i) {
-            QWidget * next = l.at(i);
-            if (next->window() == fp->window()) {
-                fp = next;
-                if (fp->focusPolicy() != Qt::NoFocus)
-                    break;
-            }
+        QWidget *next = fpx; //NOTE: we start from "first->focusProxy()"
+        while (next->window() == fpx->window() && l.contains(next)) {
+            if (next->focusPolicy() != Qt::NoFocus)
+                f_end = next;
+            next = next->d_func()->focus_next; // i.e. next->nextInFocusChain();
         }
-        first = fp;
-    }
+        if (f_end == 0) {
+            // first->focusProxy() is not a child of first:
+            f_end = fpx;
+        }
+    } else
+        f_end = first;
 
-    if (fp == second)
+    if (f_end == second)
         return;
 
-    if (QWidget *sp = second->focusProxy())
-        second = sp;
+    QWidget *s_start = second;
+    QWidget *spx = second->focusProxy();
+    QWidget *s_end = 0;
+    if (spx) {
+        QList<QWidget *> l = qFindChildren<QWidget *>(second);
+        QWidget *next = spx; //NOTE: we start from "second->focusProxy()"
+        while (next->window() == spx->window() && l.contains(next)) {
+            if (next->focusPolicy() != Qt::NoFocus)
+                s_end = next;
+            next = next->d_func()->focus_next; // i.e. next->nextInFocusChain();
+        }
+        if (s_end == 0) {
+            // second->focusProxy() is not a child of second:
+            s_start = spx;
+            s_end = spx;
+        }
+    } else 
+        s_end = second;
 
-//    QWidget *fp = first->d_func()->focus_prev;
-    QWidget *fn = first->d_func()->focus_next;
+    //place before which we will "paste" range (s_start, s_end)
+    QWidget *fn = f_end->d_func()->focus_next;
 
-    if (fn == second || first == second)
+    if (fn == s_end || f_end == s_start)
         return;
 
-    QWidget *sp = second->d_func()->focus_prev;
-    QWidget *sn = second->d_func()->focus_next;
+    // remember "loose ends" of focus chain, left after cutting out (s_start, s_end)
+    QWidget *sp = s_start->d_func()->focus_prev;
+    QWidget *sn = s_end->d_func()->focus_next;
 
-    fn->d_func()->focus_prev = second;
-    first->d_func()->focus_next = second;
+    fn->d_func()->focus_prev = s_end;
+    f_end->d_func()->focus_next = s_start;
 
-    second->d_func()->focus_next = fn;
-    second->d_func()->focus_prev = first;
+    s_end->d_func()->focus_next = fn;
+    s_start->d_func()->focus_prev = f_end;
 
+    // reconnect the loose ends:
     sp->d_func()->focus_next = sn;
     sn->d_func()->focus_prev = sp;
 
+    Q_ASSERT(f_end->d_func()->focus_next->d_func()->focus_prev == f_end);
+    Q_ASSERT(f_end->d_func()->focus_prev->d_func()->focus_next == f_end);
+
+    Q_ASSERT(fn->d_func()->focus_next->d_func()->focus_prev == fn);
+    Q_ASSERT(fn->d_func()->focus_prev->d_func()->focus_next == fn);
+
+    Q_ASSERT(s_start->d_func()->focus_next->d_func()->focus_prev == s_start);
+    Q_ASSERT(s_start->d_func()->focus_prev->d_func()->focus_next == s_start);
+
+    Q_ASSERT(s_end->d_func()->focus_next->d_func()->focus_prev == s_end);
+    Q_ASSERT(s_end->d_func()->focus_prev->d_func()->focus_next == s_end);
 
-    Q_ASSERT(first->d_func()->focus_next->d_func()->focus_prev == first);
-    Q_ASSERT(first->d_func()->focus_prev->d_func()->focus_next == first);
+    Q_ASSERT(sp->d_func()->focus_next->d_func()->focus_prev == sp);
+    Q_ASSERT(sp->d_func()->focus_prev->d_func()->focus_next == sp);
 
-    Q_ASSERT(second->d_func()->focus_next->d_func()->focus_prev == second);
-    Q_ASSERT(second->d_func()->focus_prev->d_func()->focus_next == second);
+    Q_ASSERT(sn->d_func()->focus_next->d_func()->focus_prev == sn);
+    Q_ASSERT(sn->d_func()->focus_prev->d_func()->focus_next == sn);
 }
 
 /*!\internal
