libyui
3.0.10
|
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: YDialogSpy.cc 00020 00021 Author: Stefan Hundhammer <sh@suse.de> 00022 00023 /-*/ 00024 00025 #include <sstream> 00026 00027 #define YUILogComponent "ui-dialog-spy" 00028 #include "YUILog.h" 00029 00030 #include <YDialogSpy.h> 00031 #include <YWidgetFactory.h> 00032 #include <YDialog.h> 00033 #include <YEvent.h> 00034 #include <YTable.h> 00035 #include <YTree.h> 00036 #include <YTreeItem.h> 00037 #include <YLayoutBox.h> 00038 #include <YAlignment.h> 00039 #include <YButtonBox.h> 00040 #include <YPushButton.h> 00041 #include <YReplacePoint.h> 00042 #include <YUI.h> 00043 00044 #define TREE_VWEIGHT 40 00045 #define PROP_VWEIGHT 60 00046 00047 #define DIA_HEIGHT 24 00048 00049 #define TREE_HEIGHT 10 00050 #define TREE_WIDTH 50 00051 00052 #define PROP_HEIGHT 12 00053 #define PROP_WIDTH 50 00054 00055 00056 /** 00057 * Custom tree item class to map tree items to widgets 00058 **/ 00059 class YWidgetTreeItem: public YTreeItem 00060 { 00061 public: 00062 YWidgetTreeItem( YWidget * widget, 00063 bool isOpen ) 00064 : YTreeItem( "", isOpen ) 00065 , _widget( widget ) 00066 { 00067 setWidgetLabel(); 00068 } 00069 00070 YWidgetTreeItem( YWidgetTreeItem * parent, 00071 YWidget * widget, 00072 bool isOpen ) 00073 : YTreeItem( parent, "", isOpen ) 00074 , _widget( widget ) 00075 { 00076 setWidgetLabel(); 00077 } 00078 00079 virtual ~YWidgetTreeItem() {} 00080 YWidget * widget() const { return _widget; } 00081 00082 00083 protected: 00084 00085 void setWidgetLabel() 00086 { 00087 std::ostringstream str; 00088 str << _widget; 00089 setLabel( str.str() ); 00090 } 00091 00092 private: 00093 YWidget * _widget; 00094 }; 00095 00096 00097 static void fillTree( YWidgetTreeItem * parent, 00098 YWidgetListConstIterator begin, 00099 YWidgetListConstIterator end, 00100 int treeLevel ); 00101 00102 00103 00104 00105 struct YDialogSpyPrivate 00106 { 00107 YDialogSpyPrivate() 00108 : targetDialog( 0 ) 00109 , spyDialog( 0 ) 00110 , widgetTree( 0 ) 00111 , propButton( 0 ) 00112 , propReplacePoint( 0 ) 00113 , propTable( 0 ) 00114 , closeButton( 0 ) 00115 {} 00116 00117 YDialog * targetDialog; // Dialog that is being inspected 00118 YDialog * spyDialog; // Debug dialog that shows widget data 00119 YTree * widgetTree; // Tree widget to show widget hierarchy 00120 YPushButton * propButton; 00121 YReplacePoint * propReplacePoint; 00122 YTable * propTable; 00123 YPushButton * closeButton; 00124 }; 00125 00126 00127 00128 YDialogSpy::YDialogSpy( YDialog * targetDialog ) 00129 : priv( new YDialogSpyPrivate() ) 00130 { 00131 if ( ! targetDialog ) 00132 targetDialog = YDialog::topmostDialog(); 00133 00134 priv->targetDialog = targetDialog; 00135 YWidgetFactory * fac = YUI::widgetFactory(); 00136 00137 priv->spyDialog = fac->createPopupDialog(); 00138 YAlignment * diaMin = fac->createMinHeight( priv->spyDialog, DIA_HEIGHT ); 00139 YLayoutBox * vbox = fac->createVBox( diaMin ); 00140 00141 YAlignment * minSize = fac->createMinSize( vbox, TREE_WIDTH, TREE_HEIGHT ); 00142 minSize->setWeight( YD_VERT, TREE_VWEIGHT ); 00143 priv->widgetTree = fac->createTree( minSize, "Widget &Tree", false ); 00144 priv->widgetTree->setNotify( true ); 00145 00146 YWidgetTreeItem * rootItem = new YWidgetTreeItem( targetDialog, true ); 00147 YUI_CHECK_NEW( rootItem ); 00148 fillTree( rootItem, targetDialog->childrenBegin(), targetDialog->childrenEnd(), 1 ); 00149 priv->widgetTree->addItem( rootItem ); 00150 priv->widgetTree->rebuildTree(); 00151 00152 YAlignment * alignment = fac->createLeft( vbox ); 00153 priv->propButton = fac->createPushButton( alignment, "&Properties >>>" ); 00154 priv->propReplacePoint = fac->createReplacePoint( vbox ); 00155 fac->createEmpty( priv->propReplacePoint ); 00156 00157 YButtonBox * buttonBox = fac->createButtonBox( vbox ); 00158 priv->closeButton = fac->createPushButton( buttonBox, "&Close" ); 00159 priv->closeButton->setRole( YOKButton ); 00160 } 00161 00162 00163 YDialogSpy::~YDialogSpy() 00164 { 00165 if ( priv->spyDialog ) 00166 priv->spyDialog->destroy(); 00167 } 00168 00169 00170 bool YDialogSpy::propertiesShown() const 00171 { 00172 return priv->propTable != 0; 00173 } 00174 00175 00176 void YDialogSpy::showProperties() 00177 { 00178 if ( ! propertiesShown() ) 00179 { 00180 priv->propReplacePoint->deleteChildren(); 00181 priv->propReplacePoint->setWeight( YD_VERT, PROP_VWEIGHT ); 00182 00183 YWidgetFactory * fac = YUI::widgetFactory(); 00184 YAlignment * minSize = fac->createMinSize( priv->propReplacePoint, 00185 PROP_WIDTH, PROP_HEIGHT ); 00186 YTableHeader * header = new YTableHeader(); 00187 YUI_CHECK_NEW( header ); 00188 header->addColumn( "Property" ); 00189 header->addColumn( "Value" ); 00190 header->addColumn( "Type" ); 00191 00192 priv->propTable = fac->createTable( minSize, header ); 00193 // priv->propTable->setKeepSorting( true ); 00194 00195 priv->propButton->setLabel( "<<< &Properties" ); 00196 priv->propReplacePoint->showChild(); 00197 priv->spyDialog->recalcLayout(); 00198 } 00199 } 00200 00201 00202 void YDialogSpy::hideProperties() 00203 { 00204 if ( propertiesShown() ) 00205 { 00206 priv->propReplacePoint->deleteChildren(); 00207 priv->propReplacePoint->setWeight( YD_VERT, 0 ); 00208 priv->propTable = 0; 00209 YUI::widgetFactory()->createEmpty( priv->propReplacePoint ); 00210 00211 priv->propButton->setLabel( "&Properties >>>" ); 00212 priv->propReplacePoint->showChild(); 00213 priv->spyDialog->recalcLayout(); 00214 } 00215 } 00216 00217 00218 void YDialogSpy::showProperties( YWidget * widget ) 00219 { 00220 if ( ! priv->propTable ) 00221 return; 00222 00223 priv->propTable->deleteAllItems(); 00224 00225 if ( widget ) 00226 { 00227 YPropertySet propSet = widget->propertySet(); 00228 YItemCollection items; 00229 items.reserve( propSet.size() ); 00230 00231 for ( YPropertySet::const_iterator it = propSet.propertiesBegin(); 00232 it != propSet.propertiesEnd(); 00233 ++it ) 00234 { 00235 YProperty prop = *it; 00236 YPropertyValue propVal = widget->getProperty( prop.name() ); 00237 std::string propValStr; 00238 00239 switch ( prop.type() ) 00240 { 00241 case YStringProperty: 00242 propValStr = propVal.stringVal(); 00243 break; 00244 00245 case YBoolProperty: 00246 propValStr = propVal.boolVal() ? "true" : "false"; 00247 break; 00248 00249 case YIntegerProperty: 00250 { 00251 std::ostringstream str; 00252 str << propVal.integerVal(); 00253 propValStr = str.str(); 00254 } 00255 break; 00256 00257 default: 00258 propValStr = "???"; 00259 break; 00260 } 00261 00262 YTableItem * item = new YTableItem( prop.name(), propValStr, prop.typeAsStr() ); 00263 YUI_CHECK_NEW( item ); 00264 items.push_back( item ); 00265 } 00266 00267 priv->propTable->addItems( items ); 00268 priv->propTable->deselectAllItems(); 00269 } 00270 } 00271 00272 00273 void fillTree( YWidgetTreeItem * parent, 00274 YWidgetListConstIterator begin, 00275 YWidgetListConstIterator end, 00276 int treeLevel ) 00277 { 00278 for ( YWidgetListConstIterator it = begin; it != end; ++it ) 00279 { 00280 YWidget * widget = *it; 00281 YWidgetTreeItem * item = new YWidgetTreeItem( parent, widget, treeLevel < 4 ); 00282 00283 if ( widget->hasChildren() ) 00284 fillTree( item, widget->childrenBegin(), widget->childrenEnd(), treeLevel+1 ); 00285 } 00286 } 00287 00288 00289 void YDialogSpy::exec() 00290 { 00291 YUI_CHECK_PTR( priv->spyDialog ); 00292 00293 while ( true ) 00294 { 00295 bool updateProp = false; 00296 YEvent * event = priv->spyDialog->waitForEvent(); 00297 yuiMilestone() << "dialog: " << priv->spyDialog->preferredHeight(); 00298 yuiMilestone() << "tree: " << priv->widgetTree->preferredHeight(); 00299 00300 if ( event ) 00301 { 00302 if ( event->widget() == priv->closeButton || 00303 event->eventType() == YEvent::CancelEvent ) // window manager "close window" button 00304 { 00305 priv->targetDialog->highlight( 0 ); 00306 return; 00307 } 00308 00309 if ( event->widget() == priv->propButton ) 00310 { 00311 if ( propertiesShown() ) 00312 hideProperties(); 00313 else 00314 { 00315 showProperties(); 00316 updateProp = true; 00317 } 00318 } 00319 00320 if ( event->widget() == priv->widgetTree || updateProp ) 00321 { 00322 YWidgetTreeItem * item = (YWidgetTreeItem *) priv->widgetTree->selectedItem(); 00323 yuiDebug() << "Highlighting " << item << std::endl; 00324 00325 if ( item ) 00326 { 00327 priv->targetDialog->highlight( item->widget() ); 00328 showProperties( item->widget() ); 00329 } 00330 } 00331 } 00332 } 00333 } 00334 00335 00336 void YDialogSpy::showDialogSpy( YDialog * dialog ) 00337 { 00338 try 00339 { 00340 YDialogSpy dialogSpy( dialog ); 00341 dialogSpy.exec(); 00342 } 00343 catch ( YUIException & exception ) 00344 { 00345 YUI_CAUGHT( exception ); 00346 } 00347 }