1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svx.hxx" 30 31 #include "tabwin.hxx" 32 #include "svx/fmtools.hxx" 33 #include "fmservs.hxx" 34 #include "stringlistresource.hxx" 35 36 #include <svx/svxids.hrc> 37 #include <svx/dbaexchange.hxx> 38 #include <com/sun/star/sdb/CommandType.hpp> 39 #include <com/sun/star/sdbcx/XTablesSupplier.hpp> 40 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 41 #include <com/sun/star/sdbc/XPreparedStatement.hpp> 42 #include <com/sun/star/awt/XControlContainer.hpp> 43 #include <com/sun/star/util/XLocalizedAliases.hpp> 44 #include <comphelper/processfactory.hxx> 45 #include <comphelper/stl_types.hxx> 46 47 #ifndef _SVX_FMHELP_HRC 48 #include "fmhelp.hrc" 49 #endif 50 #include <svx/fmshell.hxx> 51 #include "fmshimp.hxx" 52 #include "svx/dbtoolsclient.hxx" 53 #include <svx/fmpage.hxx> 54 55 #ifndef _SVX_FMPGEIMP_HXX 56 #include "fmpgeimp.hxx" 57 #endif 58 59 #ifndef _SVX_FMPROP_HRC 60 #include "fmprop.hrc" 61 #endif 62 63 #ifndef _SVX_FMRESIDS_HRC 64 #include "svx/fmresids.hrc" 65 #endif 66 #include <svx/dialmgr.hxx> 67 #include <tools/shl.hxx> 68 #include <svx/svdpagv.hxx> 69 #include <sfx2/objitem.hxx> 70 #include <sfx2/dispatch.hxx> 71 #include <comphelper/property.hxx> 72 #include <sfx2/frame.hxx> 73 #include <svx/dataaccessdescriptor.hxx> 74 75 const long STD_WIN_POS_X = 50; 76 const long STD_WIN_POS_Y = 50; 77 78 const long STD_WIN_SIZE_X = 120; 79 const long STD_WIN_SIZE_Y = 150; 80 81 const long MIN_WIN_SIZE_X = 50; 82 const long MIN_WIN_SIZE_Y = 50; 83 84 const long LISTBOX_BORDER = 2; 85 86 using namespace ::com::sun::star::sdbc; 87 using namespace ::com::sun::star::sdb; 88 using namespace ::com::sun::star::uno; 89 using namespace ::com::sun::star::datatransfer; 90 using namespace ::com::sun::star::beans; 91 using namespace ::com::sun::star::lang; 92 using namespace ::com::sun::star::form; 93 using namespace ::com::sun::star::container; 94 using namespace ::com::sun::star; 95 using namespace ::svxform; 96 using namespace ::svx; 97 98 99 struct ColumnInfo 100 { 101 ::rtl::OUString sColumnName; 102 ::rtl::OUString sLabel; 103 bool bColumn; 104 ColumnInfo(const ::rtl::OUString& i_sColumnName,const ::rtl::OUString& i_sLabel) 105 : sColumnName(i_sColumnName) 106 , sLabel(i_sLabel) 107 , bColumn(true) 108 { 109 } 110 ColumnInfo(const ::rtl::OUString& i_sColumnName) 111 : sColumnName(i_sColumnName) 112 , bColumn(false) 113 { 114 } 115 }; 116 117 void lcl_addToList( SvTreeListBox& _rListBox, const uno::Reference< container::XNameAccess>& i_xColumns ) 118 { 119 uno::Sequence< ::rtl::OUString > aEntries = i_xColumns->getElementNames(); 120 const ::rtl::OUString* pEntries = aEntries.getConstArray(); 121 sal_Int32 nEntries = aEntries.getLength(); 122 for ( sal_Int32 i = 0; i < nEntries; ++i, ++pEntries ) 123 { 124 uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(*pEntries),UNO_QUERY_THROW); 125 ::rtl::OUString sLabel; 126 if ( xColumn->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL) ) 127 xColumn->getPropertyValue(FM_PROP_LABEL) >>= sLabel; 128 if ( sLabel.getLength() ) 129 _rListBox.InsertEntry( sLabel,NULL,sal_False,LIST_APPEND,new ColumnInfo(*pEntries,sLabel) ); 130 else 131 _rListBox.InsertEntry( *pEntries,NULL,sal_False,LIST_APPEND,new ColumnInfo(*pEntries,sLabel) ); 132 } 133 } 134 //================================================================== 135 // class FmFieldWinListBox 136 //================================================================== 137 DBG_NAME(FmFieldWinListBox) 138 //------------------------------------------------------------------------------ 139 FmFieldWinListBox::FmFieldWinListBox( FmFieldWin* pParent ) 140 :SvTreeListBox( pParent, WB_HASBUTTONS|WB_BORDER ) 141 ,pTabWin( pParent ) 142 { 143 DBG_CTOR(FmFieldWinListBox,NULL); 144 SetHelpId( HID_FIELD_SEL ); 145 146 SetHighlightRange( ); 147 } 148 149 //------------------------------------------------------------------------------ 150 FmFieldWinListBox::~FmFieldWinListBox() 151 { 152 DBG_DTOR(FmFieldWinListBox,NULL); 153 } 154 155 //------------------------------------------------------------------------------ 156 sal_Int8 FmFieldWinListBox::AcceptDrop( const AcceptDropEvent& /*rEvt*/ ) 157 { 158 return DND_ACTION_NONE; 159 } 160 161 //------------------------------------------------------------------------------ 162 sal_Int8 FmFieldWinListBox::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ ) 163 { 164 return DND_ACTION_NONE; 165 } 166 167 //------------------------------------------------------------------------------ 168 sal_Bool FmFieldWinListBox::DoubleClickHdl() 169 { 170 if ( pTabWin->createSelectionControls() ) 171 return sal_True; 172 173 return SvTreeListBox::DoubleClickHdl(); 174 } 175 176 //------------------------------------------------------------------------------ 177 void FmFieldWinListBox::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ ) 178 { 179 SvLBoxEntry* pSelected = FirstSelected(); 180 if (!pSelected) 181 // no drag without a field 182 return; 183 184 ::svx::ODataAccessDescriptor aDescriptor; 185 aDescriptor[ daDataSource ] <<= pTabWin->GetDatabaseName(); 186 aDescriptor[ daConnection ] <<= pTabWin->GetConnection().getTyped(); 187 aDescriptor[ daCommand ] <<= pTabWin->GetObjectName(); 188 aDescriptor[ daCommandType ]<<= pTabWin->GetObjectType(); 189 ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData()); 190 aDescriptor[ daColumnName ] <<= pInfo->sColumnName; 191 192 TransferableHelper* pTransferColumn = new OColumnTransferable( 193 aDescriptor, CTF_FIELD_DESCRIPTOR | CTF_CONTROL_EXCHANGE | CTF_COLUMN_DESCRIPTOR 194 ); 195 Reference< XTransferable> xEnsureDelete = pTransferColumn; 196 if (pTransferColumn) 197 { 198 EndSelection(); 199 pTransferColumn->StartDrag( this, DND_ACTION_COPY ); 200 } 201 } 202 203 //======================================================================== 204 // class FmFieldWinData 205 //======================================================================== 206 DBG_NAME(FmFieldWinData); 207 //----------------------------------------------------------------------- 208 FmFieldWinData::FmFieldWinData() 209 { 210 DBG_CTOR(FmFieldWinData,NULL); 211 } 212 213 //----------------------------------------------------------------------- 214 FmFieldWinData::~FmFieldWinData() 215 { 216 DBG_DTOR(FmFieldWinData,NULL); 217 } 218 219 //======================================================================== 220 // class FmFieldWin 221 //======================================================================== 222 DBG_NAME(FmFieldWin); 223 //----------------------------------------------------------------------- 224 FmFieldWin::FmFieldWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, Window* _pParent) 225 :SfxFloatingWindow(_pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE)) 226 ,SfxControllerItem(SID_FM_FIELDS_CONTROL, *_pBindings) 227 ,::comphelper::OPropertyChangeListener(m_aMutex) 228 ,pData(new FmFieldWinData) 229 ,m_nObjectType(0) 230 ,m_pChangeListener(NULL) 231 { 232 DBG_CTOR(FmFieldWin,NULL); 233 SetHelpId( HID_FIELD_SEL_WIN ); 234 235 SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) ); 236 pListBox = new FmFieldWinListBox( this ); 237 pListBox->Show(); 238 UpdateContent(NULL); 239 SetSizePixel(Size(STD_WIN_SIZE_X,STD_WIN_SIZE_Y)); 240 } 241 242 //----------------------------------------------------------------------- 243 FmFieldWin::~FmFieldWin() 244 { 245 if (m_pChangeListener) 246 { 247 m_pChangeListener->dispose(); 248 m_pChangeListener->release(); 249 // delete m_pChangeListener; 250 } 251 delete pListBox; 252 delete pData; 253 DBG_DTOR(FmFieldWin,NULL); 254 } 255 256 //----------------------------------------------------------------------- 257 void FmFieldWin::GetFocus() 258 { 259 if ( pListBox ) 260 pListBox->GrabFocus(); 261 else 262 SfxFloatingWindow::GetFocus(); 263 } 264 265 //----------------------------------------------------------------------- 266 sal_Bool FmFieldWin::createSelectionControls( ) 267 { 268 SvLBoxEntry* pSelected = pListBox->FirstSelected(); 269 if ( pSelected ) 270 { 271 // build a descriptor for the currently selected field 272 ODataAccessDescriptor aDescr; 273 aDescr.setDataSource(GetDatabaseName()); 274 275 aDescr[ daConnection ] <<= GetConnection().getTyped(); 276 277 aDescr[ daCommand ] <<= GetObjectName(); 278 aDescr[ daCommandType ] <<= GetObjectType(); 279 ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData()); 280 aDescr[ daColumnName ] <<= pInfo->sColumnName;//::rtl::OUString( pListBox->GetEntryText( pSelected) ); 281 282 // transfer this to the SFX world 283 SfxUnoAnyItem aDescriptorItem( SID_FM_DATACCESS_DESCRIPTOR, makeAny( aDescr.createPropertyValueSequence() ) ); 284 const SfxPoolItem* pArgs[] = 285 { 286 &aDescriptorItem, NULL 287 }; 288 289 // execute the create slot 290 GetBindings().Execute( SID_FM_CREATE_FIELDCONTROL, pArgs ); 291 } 292 293 return NULL != pSelected; 294 } 295 296 //----------------------------------------------------------------------- 297 long FmFieldWin::PreNotify( NotifyEvent& _rNEvt ) 298 { 299 if ( EVENT_KEYINPUT == _rNEvt.GetType() ) 300 { 301 const KeyCode& rKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode(); 302 if ( ( 0 == rKeyCode.GetModifier() ) && ( KEY_RETURN == rKeyCode.GetCode() ) ) 303 { 304 if ( createSelectionControls() ) 305 return 1; 306 } 307 } 308 309 return SfxFloatingWindow::PreNotify( _rNEvt ); 310 } 311 312 //----------------------------------------------------------------------- 313 sal_Bool FmFieldWin::Close() 314 { 315 return SfxFloatingWindow::Close(); 316 } 317 318 //----------------------------------------------------------------------- 319 void FmFieldWin::_propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw( ::com::sun::star::uno::RuntimeException ) 320 { 321 ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm(evt.Source, ::com::sun::star::uno::UNO_QUERY); 322 UpdateContent(xForm); 323 } 324 325 //----------------------------------------------------------------------- 326 void FmFieldWin::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState) 327 { 328 if (!pState || SID_FM_FIELDS_CONTROL != nSID) 329 return; 330 331 if (eState >= SFX_ITEM_AVAILABLE) 332 { 333 FmFormShell* pShell = PTR_CAST(FmFormShell,((SfxObjectItem*)pState)->GetShell()); 334 UpdateContent(pShell); 335 } 336 else 337 UpdateContent(NULL); 338 } 339 340 //----------------------------------------------------------------------- 341 void FmFieldWin::UpdateContent(FmFormShell* pShell) 342 { 343 pListBox->Clear(); 344 String aTitle( SVX_RES( RID_STR_FIELDSELECTION ) ); 345 SetText( aTitle ); 346 347 if (!pShell || !pShell->GetImpl()) 348 return; 349 350 Reference< XForm > xForm = pShell->GetImpl()->getCurrentForm(); 351 if ( xForm.is() ) 352 UpdateContent( xForm ); 353 } 354 355 //----------------------------------------------------------------------- 356 void FmFieldWin::UpdateContent(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > & xForm) 357 { 358 try 359 { 360 // ListBox loeschen 361 pListBox->Clear(); 362 UniString aTitle(SVX_RES(RID_STR_FIELDSELECTION)); 363 SetText(aTitle); 364 365 if (!xForm.is()) 366 return; 367 368 Reference< XPreparedStatement > xStatement; 369 Reference< XPropertySet > xSet(xForm, UNO_QUERY); 370 371 m_aObjectName = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_COMMAND)); 372 m_aDatabaseName = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_DATASOURCE)); 373 m_nObjectType = ::comphelper::getINT32(xSet->getPropertyValue(FM_PROP_COMMANDTYPE)); 374 375 // get the connection of the form 376 OStaticDataAccessTools aTools; 377 m_aConnection.reset( 378 aTools.connectRowset( Reference< XRowSet >( xForm, UNO_QUERY ), ::comphelper::getProcessServiceFactory(), sal_True ), 379 SharedConnection::NoTakeOwnership 380 ); 381 // TODO: When incompatible changes (such as extending the "virtualdbtools" interface by ensureRowSetConnection) 382 // are allowed, again, we should change this: dbtools should consistently use SharedConnection all over 383 // the place, and connectRowset should be replaced with ensureRowSetConnection 384 385 // get the fields of the object 386 387 if ( m_aConnection.is() && m_aObjectName.getLength() ) 388 { 389 Reference< XComponent > xKeepFieldsAlive; 390 Reference< XNameAccess > xColumns = getFieldsByCommandDescriptor( m_aConnection, m_nObjectType, m_aObjectName,xKeepFieldsAlive ); 391 if ( xColumns.is() ) 392 lcl_addToList(*pListBox,xColumns); 393 } 394 395 // Prefix setzen 396 UniString aPrefix; 397 StringListResource aPrefixes( SVX_RES( RID_RSC_TABWIN_PREFIX ) ); 398 399 switch (m_nObjectType) 400 { 401 case CommandType::TABLE: 402 aPrefix = aPrefixes[0]; 403 break; 404 case CommandType::QUERY: 405 aPrefix = aPrefixes[1]; 406 break; 407 default: 408 aPrefix = aPrefixes[2]; 409 break; 410 } 411 412 // an dem PropertySet nach Aenderungen der ControlSource lauschen 413 if (m_pChangeListener) 414 { 415 m_pChangeListener->dispose(); 416 m_pChangeListener->release(); 417 } 418 m_pChangeListener = new ::comphelper::OPropertyChangeMultiplexer(this, xSet); 419 m_pChangeListener->acquire(); 420 m_pChangeListener->addProperty(FM_PROP_DATASOURCE); 421 m_pChangeListener->addProperty(FM_PROP_COMMAND); 422 m_pChangeListener->addProperty(FM_PROP_COMMANDTYPE); 423 424 // Titel setzen 425 aTitle.AppendAscii(" "); 426 aTitle += aPrefix; 427 aTitle.AppendAscii(" "); 428 aTitle += m_aObjectName.getStr(); 429 SetText( aTitle ); 430 } 431 catch( const Exception& ) 432 { 433 DBG_ERROR( "FmTabWin::UpdateContent: caught an exception!" ); 434 } 435 } 436 437 //----------------------------------------------------------------------- 438 void FmFieldWin::Resize() 439 { 440 SfxFloatingWindow::Resize(); 441 442 Point aPos(GetPosPixel()); 443 Size aOutputSize( GetOutputSizePixel() ); 444 445 ////////////////////////////////////////////////////////////////////// 446 447 // Groesse der ::com::sun::star::form::ListBox anpassen 448 Point aLBPos( LISTBOX_BORDER, LISTBOX_BORDER ); 449 Size aLBSize( aOutputSize ); 450 aLBSize.Width() -= (2*LISTBOX_BORDER); 451 aLBSize.Height() -= (2*LISTBOX_BORDER); 452 453 pListBox->SetPosSizePixel( aLBPos, aLBSize ); 454 } 455 456 //----------------------------------------------------------------------- 457 void FmFieldWin::FillInfo( SfxChildWinInfo& rInfo ) const 458 { 459 rInfo.bVisible = sal_False; 460 } 461 462 //----------------------------------------------------------------------- 463 SFX_IMPL_FLOATINGWINDOW(FmFieldWinMgr, SID_FM_ADD_FIELD) 464 465 //----------------------------------------------------------------------- 466 FmFieldWinMgr::FmFieldWinMgr(Window* _pParent, sal_uInt16 _nId, 467 SfxBindings* _pBindings, SfxChildWinInfo* _pInfo) 468 :SfxChildWindow(_pParent, _nId) 469 { 470 pWindow = new FmFieldWin(_pBindings, this, _pParent); 471 SetHideNotDelete(sal_True); 472 eChildAlignment = SFX_ALIGN_NOALIGNMENT; 473 ((SfxFloatingWindow*)pWindow)->Initialize( _pInfo ); 474 } 475 476 477