KTutorial
0.5.1
|
00001 /*************************************************************************** 00002 * Copyright (C) 2010 by Daniel Calviño Sánchez <danxuliu@gmail.com> * 00003 * Copyright (C) 2012 by Daniel Calviño Sánchez <danxuliu@gmail.com> * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program; If not, see <http://www.gnu.org/licenses/>. * 00017 ***************************************************************************/ 00018 00019 #include "WindowOnTopEnforcer.h" 00020 00021 #include <QWidget> 00022 00023 #include "../common/WindowVisibilitySpy.h" 00024 00025 using ktutorial::common::WindowVisibilitySpy; 00026 00027 namespace ktutorial { 00028 namespace view { 00029 00030 //public: 00031 00032 WindowOnTopEnforcer::WindowOnTopEnforcer(QWidget* widget): QObject(widget), 00033 mWidgetToKeepOnTop(widget) { 00034 00035 Q_ASSERT(widget); 00036 00037 mParentStack.push(mWidgetToKeepOnTop->parentWidget()); 00038 } 00039 00040 void WindowOnTopEnforcer::setBaseWindow(QWidget* baseWindow) { 00041 Q_ASSERT(baseWindow); 00042 00043 WindowVisibilitySpy* spy = new WindowVisibilitySpy(this); 00044 spy->addWidgetToSpy(baseWindow); 00045 connect(spy, SIGNAL(windowShown(QWidget*)), 00046 this, SLOT(handleWindowShown(QWidget*))); 00047 connect(spy, SIGNAL(windowHidden(QWidget*)), 00048 this, SLOT(handleWindowHidden(QWidget*))); 00049 } 00050 00051 //private: 00052 00053 bool WindowOnTopEnforcer::isAncestorOf(QObject* object, 00054 QObject* childObject) const { 00055 if (childObject->parent() == 0) { 00056 return false; 00057 } 00058 00059 if (childObject->parent() == object) { 00060 return true; 00061 } 00062 00063 return isAncestorOf(object, childObject->parent()); 00064 } 00065 00066 void WindowOnTopEnforcer::reparentWindowTo(QWidget* window, 00067 QWidget* parent) const { 00068 //When a widget is reparented it is hidden and its window flags are cleared, 00069 //so they must be restored and the widget shown again 00070 Qt::WindowFlags flags = window->windowFlags(); 00071 window->setParent(parent); 00072 window->setWindowFlags(flags); 00073 window->show(); 00074 } 00075 00076 //private slots: 00077 00078 void WindowOnTopEnforcer::handleWindowShown(QWidget* window) { 00079 Q_ASSERT(window); 00080 00081 if (!window->isModal() || mParentStack.contains(window)) { 00082 return; 00083 } 00084 00085 //If the modal window shown is ancestor of any of the modal windows already 00086 //shown just insert it at the appropriate place in the parent stack. 00087 for (int i=1; i<mParentStack.size(); ++i) { 00088 QWidget* widgetInStack = mParentStack[i]; 00089 00090 if (!isAncestorOf(widgetInStack, window) && 00091 isAncestorOf(window, widgetInStack)) { 00092 mParentStack.insert(i, window); 00093 return; 00094 } 00095 } 00096 00097 mParentStack.push(window); 00098 00099 reparentWindowTo(mWidgetToKeepOnTop, window); 00100 } 00101 00102 void WindowOnTopEnforcer::handleWindowHidden(QWidget* window) { 00103 Q_ASSERT(window); 00104 00105 if (!window->isModal() || !mParentStack.contains(window)) { 00106 return; 00107 } 00108 00109 if (window != mParentStack.top()) { 00110 mParentStack.remove(mParentStack.indexOf(window)); 00111 return; 00112 } 00113 00114 mParentStack.pop(); 00115 00116 reparentWindowTo(mWidgetToKeepOnTop, mParentStack.top()); 00117 } 00118 00119 } 00120 }