libyui-qt
2.43.5
|
00001 /* 00002 Copyright (C) 2000-2012 Novell, Inc 00003 This library is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU Lesser General Public License as 00005 published by the Free Software Foundation; either version 2.1 of the 00006 License, or (at your option) version 3.0 of the License. This library 00007 is distributed in the hope that it will be useful, but WITHOUT ANY 00008 WARRANTY; without even the implied warranty of MERCHANTABILITY or 00009 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00010 License for more details. You should have received a copy of the GNU 00011 Lesser General Public License along with this library; if not, write 00012 to the Free Software Foundation, Inc., 51 Franklin Street, Fifth 00013 Floor, Boston, MA 02110-1301 USA 00014 */ 00015 00016 00017 /*-/ 00018 00019 File: YQMainWinDock.cc 00020 00021 Author: Stefan Hundhammer <sh@suse.de> 00022 00023 /-*/ 00024 00025 00026 #define YUILogComponent "qt-ui" 00027 #include <yui/YUILog.h> 00028 #include <QResizeEvent> 00029 #include "YQDialog.h" 00030 #include <YQUI.h> 00031 #include <yui/YEvent.h> 00032 #include "YQWizard.h" 00033 #include "YQMainWinDock.h" 00034 00035 #define VERBOSE_RESIZE 1 00036 00037 00038 YQMainWinDock * 00039 YQMainWinDock::mainWinDock() 00040 { 00041 static YQMainWinDock * mainWinDock = 0; 00042 00043 if ( ! mainWinDock ) 00044 mainWinDock = new YQMainWinDock(); 00045 00046 return mainWinDock; 00047 } 00048 00049 00050 YQMainWinDock::YQMainWinDock() 00051 : QWidget( 0, // parent, name 00052 YQUI::ui()->noBorder() ? 00053 Qt::FramelessWindowHint : 00054 Qt::Window ), 00055 _sideBarWidth( 0 ) 00056 { 00057 setFocusPolicy( Qt::StrongFocus ); 00058 00059 resize( YQUI::ui()->defaultSize( YD_HORIZ ), 00060 YQUI::ui()->defaultSize( YD_VERT ) ); 00061 00062 yuiDebug() << "MainWinDock initial size: " 00063 << size().width() << " x " << size().height() 00064 << std::endl; 00065 } 00066 00067 00068 YQMainWinDock::~YQMainWinDock() 00069 { 00070 // NOP 00071 } 00072 00073 00074 void 00075 YQMainWinDock::resizeEvent( QResizeEvent * event ) 00076 { 00077 if ( event ) 00078 { 00079 resize( event->size() ); 00080 resizeVisibleChild(); 00081 } 00082 } 00083 00084 00085 void 00086 YQMainWinDock::resizeVisibleChild() 00087 { 00088 for ( YQWidgetStack::reverse_iterator it = _widgetStack.rbegin(); it != _widgetStack.rend(); it++ ) 00089 { 00090 YQDialog * dialog = *it; 00091 00092 QRect rect = QRect( QPoint( 0, 0 ), size() ); 00093 00094 YQWizard * wizard = dialog->findWizard(); 00095 00096 if ( wizard ) 00097 yuiDebug() << dialog << " with " << wizard << " isSecondary: " << std::boolalpha << wizard->isSecondary() << std::endl; 00098 00099 if ( wizard && wizard->isSecondary() ) 00100 { 00101 if ( QApplication::isLeftToRight() ) 00102 rect.setLeft( 0 ); 00103 else 00104 rect.setWidth( rect.width() ); 00105 } 00106 00107 if ( dialog->rect() != rect ) 00108 { 00109 #if VERBOSE_RESIZE 00110 yuiDebug() << "Resizing child dialog " << std::hex << ( (void *) dialog ) << std::dec 00111 << " to " << rect.width() << " x " << rect.height() 00112 << std::endl; 00113 #endif 00114 dialog->setGeometry( rect ); 00115 } 00116 } 00117 } 00118 00119 00120 void 00121 YQMainWinDock::show() 00122 { 00123 QWidget::show(); 00124 00125 if ( ! _widgetStack.empty() ) 00126 { 00127 QWidget * dialog = _widgetStack.back(); 00128 dialog->raise(); 00129 dialog->show(); 00130 } 00131 } 00132 00133 00134 void 00135 YQMainWinDock::add( YQDialog * dialog ) 00136 { 00137 YUI_CHECK_PTR( dialog ); 00138 00139 // Deactivate the next-lower dialog 00140 // (the one that currently still is the topmost on the _widgetStack) 00141 activateCurrentDialog( false ); 00142 00143 dialog->raise(); 00144 dialog->show(); 00145 00146 yuiDebug() << "Adding dialog " << std::hex << (void *) dialog << std::dec 00147 << " to mainWinDock" 00148 << std::endl; 00149 00150 _widgetStack.push_back( dialog ); 00151 resizeVisibleChild(); 00152 00153 show(); 00154 } 00155 00156 00157 void 00158 YQMainWinDock::activateCurrentDialog( bool active ) 00159 { 00160 if ( _widgetStack.empty() ) 00161 return; 00162 00163 // In the normal case, the (still or again) topmost dialog needs to be 00164 // activated or deactivated directly. Since this is done on the QWidget 00165 // level, its widgetRep() is needed -- which may or may not be the same as 00166 // the YQDialog. 00167 00168 YQDialog * dialog = _widgetStack.back(); 00169 QWidget * widget = (QWidget *) dialog->widgetRep(); 00170 00171 00172 // But then, there is also the exceptional case that this dialog contains a 00173 // wizard with a steps panel. In that case, the steps panel should remain 00174 // untouched; only the right side (the work area) of that wizard is to be 00175 // activated or deactivated. 00176 00177 // probably no longer needed, now the windows (even with steps) fully overlap ?? 00178 /*YQWizard * wizard = dialog->findWizard(); 00179 00180 if ( wizard && wizard->wizardMode() == YWizardMode_Steps ) 00181 { 00182 QWidget * wizardWorkArea = wizard->workArea(); 00183 00184 if ( wizardWorkArea ) 00185 widget = wizardWorkArea; 00186 // else -> stick with dialog->widgetRep() 00187 }*/ 00188 00189 if ( widget ) 00190 widget->setEnabled( active ); 00191 } 00192 00193 00194 void 00195 YQMainWinDock::showCurrentDialog() 00196 { 00197 if ( ! _widgetStack.empty() ) 00198 { 00199 QWidget * dialog = _widgetStack.back(); 00200 yuiDebug() << "Showing dialog " << std::hex << (void *) dialog << std::dec << std::endl; 00201 dialog->raise(); 00202 update(); 00203 } 00204 } 00205 00206 00207 void 00208 YQMainWinDock::remove( YQDialog * dialog ) 00209 { 00210 if ( _widgetStack.empty() ) 00211 return; 00212 00213 if ( ! dialog ) 00214 dialog = _widgetStack.back(); 00215 00216 if ( dialog == _widgetStack.back() ) 00217 { 00218 // The most common case: 00219 // The topmost dialog is to be removed 00220 00221 _widgetStack.pop_back(); 00222 00223 yuiDebug() << "Removing dialog " << std::hex << (void *) dialog << std::dec 00224 <<" from mainWinDock" 00225 << std::endl; 00226 } 00227 else // The less common (but more generic) case: Remove any dialog 00228 { 00229 YQMainWinDock::YQWidgetStack::iterator pos = findInStack( dialog ); 00230 00231 if ( pos == _widgetStack.end() ) 00232 return; 00233 00234 yuiWarning() << "Found dialog somewhere in the middle of the widget stack" << std::endl; 00235 yuiDebug() << "Removing dialog " << std::hex << (void *) dialog << std::dec 00236 << " from mainWinDock" 00237 << std::endl; 00238 00239 _widgetStack.erase( pos ); 00240 } 00241 00242 if ( _widgetStack.empty() ) // No more main dialog? 00243 hide(); // -> hide dock 00244 else 00245 { 00246 dialog = _widgetStack.back(); // Get the next dialog from the stack 00247 dialog->raise(); // and raise it 00248 activateCurrentDialog( true ); 00249 dialog->show(); 00250 resizeVisibleChild(); 00251 } 00252 } 00253 00254 00255 YQMainWinDock::YQWidgetStack::iterator 00256 YQMainWinDock::findInStack( YQDialog * dialog ) 00257 { 00258 for ( YQMainWinDock::YQWidgetStack::iterator it = _widgetStack.begin(); 00259 it != _widgetStack.end(); 00260 ++it ) 00261 { 00262 if ( *it == dialog ) 00263 return it; 00264 } 00265 00266 return _widgetStack.end(); 00267 } 00268 00269 00270 YQDialog * 00271 YQMainWinDock::topmostDialog() const 00272 { 00273 if ( _widgetStack.empty() ) 00274 return 0; 00275 else 00276 return _widgetStack.back(); 00277 } 00278 00279 00280 bool 00281 YQMainWinDock::couldDock() 00282 { 00283 YDialog * topDialog = YDialog::topmostDialog( false ); // don't throw 00284 00285 if ( ! topDialog ) // No dialog at all? 00286 return true; // Can dock the next one without problems 00287 00288 // The next dialog can be docked if there is no popup dialog currently open. 00289 // This is equivalent to the topmost dialog on the YDialog stack being the 00290 // same dialog as the topmost dialog of this MainWinDock. 00291 00292 return topDialog->widgetRep() == this->topmostDialog(); 00293 } 00294 00295 00296 void 00297 YQMainWinDock::closeEvent( QCloseEvent * event ) 00298 { 00299 // The window manager "close window" button (and WM menu, e.g. Alt-F4) will be 00300 // handled just like the user had clicked on the `id`( `cancel ) button in 00301 // that dialog. It's up to the YCP application to handle this (if desired). 00302 00303 yuiMilestone() << "Caught window manager close event - returning with YCancelEvent" << std::endl; 00304 event->ignore(); 00305 YQUI::ui()->sendEvent( new YCancelEvent() ); 00306 } 00307 00308 00309 void 00310 YQMainWinDock::paintEvent( QPaintEvent * event ) 00311 { 00312 // NOP 00313 } 00314 00315 00316 void 00317 YQMainWinDock::setSideBarWidth( int width ) 00318 { 00319 if ( _sideBarWidth == width ) 00320 return; 00321 00322 _sideBarWidth = width; 00323 resizeVisibleChild(); 00324 } 00325 00326 00327 #include "YQMainWinDock.moc"