1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbui.hxx"
26 
27 #ifndef _DBAUI_INDEXDIALOG_HXX_
28 #include "indexdialog.hxx"
29 #endif
30 #ifndef _DBU_DLG_HRC_
31 #include "dbu_dlg.hrc"
32 #endif
33 #ifndef _DBA_DBACCESS_HELPID_HRC_
34 #include "dbaccess_helpid.hrc"
35 #endif
36 #ifndef _DBAUI_INDEXDIALOG_HRC_
37 #include "indexdialog.hrc"
38 #endif
39 #ifndef _DBAUI_INDEXFIELDSCONTROL_HXX_
40 #include "indexfieldscontrol.hxx"
41 #endif
42 #ifndef _DBAUI_INDEXCOLLECTION_HXX_
43 #include "indexcollection.hxx"
44 #endif
45 #ifndef _SV_MSGBOX_HXX
46 #include <vcl/msgbox.hxx>
47 #endif
48 #ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_
49 #include <com/sun/star/sdb/SQLContext.hpp>
50 #endif
51 #ifndef DBAUI_TOOLS_HXX
52 #include "UITools.hxx"
53 #endif
54 #ifndef _SVTOOLS_IMGDEF_HXX
55 #include <svtools/imgdef.hxx>
56 #endif
57 #ifndef DBACCESS_UI_BROWSER_ID_HXX
58 #include "browserids.hxx"
59 #endif
60 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
61 #include <connectivity/dbtools.hxx>
62 #endif
63 //......................................................................
64 namespace dbaui
65 {
66 //......................................................................
67 
68 	using namespace ::com::sun::star::uno;
69 	using namespace ::com::sun::star::container;
70 	using namespace ::com::sun::star::sdbc;
71 	using namespace ::com::sun::star::sdb;
72 	using namespace ::com::sun::star::lang;
73 	using namespace ::dbtools;
74 
75 	//==================================================================
76 	//= helper
77 	//==================================================================
78 	//------------------------------------------------------------------
operator ==(const OIndexField & _rLHS,const OIndexField & _rRHS)79 	sal_Bool operator ==(const OIndexField& _rLHS, const OIndexField& _rRHS)
80 	{
81 		return	(_rLHS.sFieldName == _rRHS.sFieldName)
82 			&&	(_rLHS.bSortAscending == _rRHS.bSortAscending);
83 	}
84 
85 	//------------------------------------------------------------------
operator !=(const OIndexField & _rLHS,const OIndexField & _rRHS)86 	sal_Bool operator !=(const OIndexField& _rLHS, const OIndexField& _rRHS)
87 	{
88 		return !(_rLHS == _rRHS);
89 	}
90 
91 	//------------------------------------------------------------------
operator ==(const IndexFields & _rLHS,const IndexFields & _rRHS)92 	sal_Bool operator ==(const IndexFields& _rLHS, const IndexFields& _rRHS)
93 	{
94 		if (_rLHS.size() != _rRHS.size())
95 			return sal_False;
96 
97 		ConstIndexFieldsIterator aLeft = _rLHS.begin();
98 		ConstIndexFieldsIterator aLeftEnd = _rLHS.end();
99 		ConstIndexFieldsIterator aRight = _rRHS.begin();
100 		for	(; aLeft != aLeftEnd; ++aLeft, ++aRight)
101 		{
102 			if (*aLeft != *aRight)
103 				return sal_False;
104 		}
105 
106 		return sal_True;
107 	}
108 
109 	//------------------------------------------------------------------
operator !=(const IndexFields & _rLHS,const IndexFields & _rRHS)110 	sal_Bool operator !=(const IndexFields& _rLHS, const IndexFields& _rRHS)
111 	{
112 		return !(_rLHS == _rRHS);
113 	}
114 
115 	//==================================================================
116 	//= DbaIndexList
117 	//==================================================================
118 	//------------------------------------------------------------------
DbaIndexList(Window * _pParent,const ResId & _rId)119 	DbaIndexList::DbaIndexList(Window* _pParent, const ResId& _rId)
120 		:SvTreeListBox(_pParent, _rId)
121 		,m_bSuspendSelectHdl(sal_False)
122 	{
123 	}
124 
125 	extern sal_Bool isCharOk(sal_Unicode _cChar,sal_Bool _bFirstChar,sal_Bool _bUpperCase,const ::rtl::OUString& _sAllowedChars);
126 	//------------------------------------------------------------------
EditedEntry(SvLBoxEntry * _pEntry,const String & _rNewText)127 	sal_Bool DbaIndexList::EditedEntry( SvLBoxEntry* _pEntry, const String& _rNewText )
128 	{
129 		// first check if this is valid SQL92 name
130 		if ( isSQL92CheckEnabled(m_xConnection) )
131 		{
132 			Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
133 			if ( xMeta.is() )
134 			{
135 				::rtl::OUString sNewName(_rNewText);
136 				::rtl::OUString sAlias = ::dbtools::convertName2SQLName(sNewName,xMeta->getExtraNameCharacters());
137 				if ( ( xMeta->supportsMixedCaseQuotedIdentifiers() )
138 						?
139 						sAlias != sNewName
140 						:
141 				!sNewName.equalsIgnoreAsciiCase(sAlias))
142 					return sal_False;
143 			}
144 		}
145 
146 		if (!SvTreeListBox::EditedEntry(_pEntry, _rNewText))
147 			return sal_False;
148 
149 		String sOldText = GetEntryText(_pEntry);
150 		SvTreeListBox::SetEntryText(_pEntry, _rNewText);
151 
152 		sal_Bool bValid = sal_True;
153 		if (m_aEndEditHdl.IsSet())
154 			bValid = (0 != m_aEndEditHdl.Call(_pEntry));
155 
156 		if (bValid)
157 			return sal_True;
158 
159 		SvTreeListBox::SetEntryText(_pEntry, sOldText);
160 
161 		return sal_False;
162 	}
163 
164 	//------------------------------------------------------------------
enableSelectHandler()165 	void DbaIndexList::enableSelectHandler()
166 	{
167 		DBG_ASSERT(m_bSuspendSelectHdl, "DbaIndexList::enableSelectHandler: invalid call (this is not cumulative)!");
168 		m_bSuspendSelectHdl = sal_False;
169 	}
170 
171 	//------------------------------------------------------------------
disableSelectHandler()172 	void DbaIndexList::disableSelectHandler()
173 	{
174 		DBG_ASSERT(!m_bSuspendSelectHdl, "DbaIndexList::enableSelectHandler: invalid call (this is not cumulative)!");
175 		m_bSuspendSelectHdl = sal_True;
176 	}
177 
178 	//------------------------------------------------------------------
SelectNoHandlerCall(SvLBoxEntry * _pEntry)179 	void DbaIndexList::SelectNoHandlerCall( SvLBoxEntry* _pEntry )
180 	{
181 		disableSelectHandler();
182 		Select(_pEntry, sal_True);
183 		enableSelectHandler();
184 	}
185 
186 	//------------------------------------------------------------------
Select(SvLBoxEntry * pEntry,sal_Bool _bSelect)187 	sal_Bool DbaIndexList::Select( SvLBoxEntry* pEntry, sal_Bool _bSelect )
188 	{
189 		sal_Bool bReturn = SvTreeListBox::Select(pEntry, _bSelect);
190 
191 		if (m_aSelectHdl.IsSet() && !m_bSuspendSelectHdl && _bSelect)
192 			m_aSelectHdl.Call(this);
193 
194 		return bReturn;
195 	}
196 
197 	//==================================================================
198 	//= DbaIndexDialog
199 	//==================================================================
DBG_NAME(DbaIndexDialog)200 DBG_NAME(DbaIndexDialog)
201 //------------------------------------------------------------------
202 	DbaIndexDialog::DbaIndexDialog(	Window* _pParent, const Sequence< ::rtl::OUString >& _rFieldNames,
203 									const Reference< XNameAccess >& _rxIndexes,
204 									const Reference< XConnection >& _rxConnection,
205 									const Reference< XMultiServiceFactory >& _rxORB,sal_Int32 _nMaxColumnsInIndex)
206 		:ModalDialog( _pParent, ModuleRes(DLG_INDEXDESIGN))
207 		,m_xConnection(_rxConnection)
208 		,m_aGeometrySettings(E_DIALOG, ::rtl::OUString::createFromAscii("dbaccess.tabledesign.indexdialog"))
209 		,m_aActions							(this, ModuleRes(TLB_ACTIONS))
210 		,m_aIndexes							(this, ModuleRes(CTR_INDEXLIST))
211 		,m_aIndexDetails					(this, ModuleRes(FL_INDEXDETAILS))
212 		,m_aDescriptionLabel				(this, ModuleRes(FT_DESC_LABEL))
213 		,m_aDescription						(this, ModuleRes(FT_DESCRIPTION))
214 		,m_aUnique							(this, ModuleRes(CB_UNIQUE))
215 		,m_aFieldsLabel						(this, ModuleRes(FT_FIELDS))
216 		,m_pFields(new IndexFieldsControl	(this, ModuleRes(CTR_FIELDS),_nMaxColumnsInIndex,::dbtools::getBooleanDataSourceSetting( m_xConnection, "AddIndexAppendix" )))
217 		,m_aClose							(this, ModuleRes(PB_CLOSE))
218 		,m_aHelp							(this, ModuleRes(HB_HELP))
219 		,m_pIndexes(NULL)
220 		,m_pPreviousSelection(NULL)
221 		,m_bEditAgain(sal_False)
222 		,m_xORB(_rxORB)
223 	{
224 		DBG_CTOR(DbaIndexDialog,NULL);
225 
226 		FreeResource();
227 
228 		m_aActions.SetSelectHdl(LINK(this, DbaIndexDialog, OnIndexAction));
229 
230 		m_aIndexes.SetSelectHdl(LINK(this, DbaIndexDialog, OnIndexSelected));
231 		m_aIndexes.SetEndEditHdl(LINK(this, DbaIndexDialog, OnEntryEdited));
232 		m_aIndexes.SetSelectionMode(SINGLE_SELECTION);
233 		m_aIndexes.SetHighlightRange();
234 		m_aIndexes.setConnection(m_xConnection);
235 
236 		m_pFields->Init(_rFieldNames);
237 
238 		setToolBox(&m_aActions);
239 
240 		m_pIndexes = new OIndexCollection();
241 		try
242 		{
243 			m_pIndexes->attach(_rxIndexes);
244 		}
245 		catch(SQLException& e)
246 		{
247 			::dbaui::showError(SQLExceptionInfo(e),_pParent,_rxORB);
248 		}
249 		catch(Exception&)
250 		{
251 			OSL_ENSURE(sal_False, "DbaIndexDialog::DbaIndexDialog: could not retrieve basic information from the UNO collection!");
252 		}
253 
254 		fillIndexList();
255 
256 		m_aUnique.SetClickHdl(LINK(this, DbaIndexDialog, OnModified));
257 		m_pFields->SetModifyHdl(LINK(this, DbaIndexDialog, OnModified));
258 
259 		m_aClose.SetClickHdl(LINK(this, DbaIndexDialog, OnCloseDialog));
260 
261 		// get our most recent geometry settings
262 //		if (m_aGeometrySettings.Exists())
263 //		{
264 //			Point aPos;
265 //			m_aGeometrySettings.GetPosition(aPos.X(), aPos.Y());
266 //			SetPosPixel(aPos);
267 //		}
268 
269 		// if all of the indexes have an empty description, we're not interested in displaying it
270 		Indexes::const_iterator aCheck;
271 
272 		for (	aCheck = m_pIndexes->begin();
273 				aCheck != m_pIndexes->end();
274 				++aCheck
275 			)
276 		{
277 			if (aCheck->sDescription.getLength())
278 				break;
279 		}
280 
281 		if (aCheck == m_pIndexes->end())
282 		{
283 			sal_Int32 nMoveUp = m_aUnique.GetPosPixel().Y() - m_aDescriptionLabel.GetPosPixel().Y();
284 
285 			// hide the controls which are necessary for the description
286 			m_aDescription.Hide();
287 			m_aDescriptionLabel.Hide();
288 
289 			// move other controls up
290 			Point aPos = m_aUnique.GetPosPixel();
291 			aPos.Y() -= nMoveUp;
292 			m_aUnique.SetPosPixel(aPos);
293 
294 			aPos = m_aFieldsLabel.GetPosPixel();
295 			aPos.Y() -= nMoveUp;
296 			m_aFieldsLabel.SetPosPixel(aPos);
297 
298 			aPos = m_pFields->GetPosPixel();
299 			aPos.Y() -= nMoveUp;
300 			m_pFields->SetPosPixel(aPos);
301 
302 			// and enlarge the fields list
303 			Size aSize = m_pFields->GetSizePixel();
304 			aSize.Height() += nMoveUp;
305 			m_pFields->SetSizePixel(aSize);
306 		}
307 	}
308 
309 	//------------------------------------------------------------------
updateToolbox()310 	void DbaIndexDialog::updateToolbox()
311 	{
312 		m_aActions.EnableItem(ID_INDEX_NEW, !m_aIndexes.IsEditingActive());
313 
314 		SvLBoxEntry* pSelected = m_aIndexes.FirstSelected();
315 		sal_Bool bSelectedAnything = NULL != pSelected;
316 
317 
318 		if (pSelected)
319 		{
320 			// is the current entry modified?
321 			Indexes::const_iterator aSelectedPos = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(pSelected->GetUserData());
322 			m_aActions.EnableItem(ID_INDEX_SAVE, aSelectedPos->isModified() || aSelectedPos->isNew());
323 			m_aActions.EnableItem(ID_INDEX_RESET, aSelectedPos->isModified() || aSelectedPos->isNew());
324 			bSelectedAnything = bSelectedAnything && !aSelectedPos->bPrimaryKey;
325 		}
326 		else
327 		{
328 			m_aActions.EnableItem(ID_INDEX_SAVE, sal_False);
329 			m_aActions.EnableItem(ID_INDEX_RESET, sal_False);
330 		}
331 		m_aActions.EnableItem(ID_INDEX_DROP, bSelectedAnything);
332 		m_aActions.EnableItem(ID_INDEX_RENAME, bSelectedAnything);
333 	}
334 
335 	//------------------------------------------------------------------
fillIndexList()336 	void DbaIndexDialog::fillIndexList()
337 	{
338 		sal_Bool bHiContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
339 		Image aPKeyIcon(ModuleRes( bHiContrast ? IMG_PKEYICON_SCH : IMG_PKEYICON));
340 		// fill the list with the index names
341 		m_aIndexes.Clear();
342 		Indexes::iterator aIndexLoop = m_pIndexes->begin();
343 		Indexes::iterator aEnd = m_pIndexes->end();
344 		for (; aIndexLoop != aEnd; ++aIndexLoop)
345 		{
346 			SvLBoxEntry* pNewEntry = NULL;
347 			if (aIndexLoop->bPrimaryKey)
348 				pNewEntry = m_aIndexes.InsertEntry(aIndexLoop->sName, aPKeyIcon, aPKeyIcon);
349 			else
350 				pNewEntry = m_aIndexes.InsertEntry(aIndexLoop->sName);
351 
352 			pNewEntry->SetUserData(reinterpret_cast< void* >(sal_Int32(aIndexLoop - m_pIndexes->begin())));
353 		}
354 
355 		OnIndexSelected(&m_aIndexes);
356 	}
357 
358 	//------------------------------------------------------------------
~DbaIndexDialog()359 	DbaIndexDialog::~DbaIndexDialog( )
360 	{
361 		setToolBox(NULL);
362 		delete m_pIndexes;
363 		delete m_pFields;
364 
365 		// save our geometry settings
366 //		Point aPos = GetPosPixel();
367 //		m_aGeometrySettings.SetPosition(aPos.X(), aPos.Y());
368 
369 		DBG_DTOR(DbaIndexDialog,NULL);
370 	}
371 
372 	//------------------------------------------------------------------
implCommit(SvLBoxEntry * _pEntry)373 	sal_Bool DbaIndexDialog::implCommit(SvLBoxEntry* _pEntry)
374 	{
375 		DBG_ASSERT(_pEntry, "DbaIndexDialog::implCommit: invalid entry!");
376 
377 		Indexes::iterator aCommitPos = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(_pEntry->GetUserData());
378 
379 		// if it's not a new index, remove it
380 		// (we can't modify indexes, only drop'n'insert)
381 		if (!aCommitPos->isNew())
382 			if (!implDropIndex(_pEntry, sal_False))
383 				return sal_False;
384 
385 		// create the new index
386 		SQLExceptionInfo aExceptionInfo;
387 		try
388 		{
389 			m_pIndexes->commitNewIndex(aCommitPos);
390 		}
391 		catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); }
392 		catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); }
393 		catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); }
394 
395 		// reflect the new selection in the toolbox
396 		updateToolbox();
397 
398 		if (aExceptionInfo.isValid())
399 			showError(aExceptionInfo, this, m_xORB);
400 		else
401 		{
402 			m_aUnique.SaveValue();
403 			m_pFields->SaveValue();
404 		}
405 
406 		return !aExceptionInfo.isValid();
407 	}
408 
409 	//------------------------------------------------------------------
OnNewIndex()410 	void DbaIndexDialog::OnNewIndex()
411 	{
412 		// commit the current entry, if necessary
413 		if (!implCommitPreviouslySelected())
414 			return;
415 
416 		// get a new unique name for the new index
417 		String sNewIndexName;
418 		const String sNewIndexNameBase(ModuleRes(STR_LOGICAL_INDEX_NAME));
419 		sal_Int32 i;
420 
421 		for ( i = 1; i < 0x7FFFFFFF; ++i )
422 		{
423 			sNewIndexName = sNewIndexNameBase;
424 			sNewIndexName += String::CreateFromInt32(i);
425 			if (m_pIndexes->end() == m_pIndexes->find(sNewIndexName))
426 				break;
427 		}
428 		if ((i>0x7FFFFFFF) || (i<0))
429 		{
430 			DBG_ERROR("DbaIndexDialog::OnNewIndex: no free index name found!");
431 			// can't do anything ... of course we try another base, but this could end with the same result ...
432 			return;
433 		}
434 
435 		SvLBoxEntry* pNewEntry = m_aIndexes.InsertEntry(sNewIndexName);
436 		m_pIndexes->insert(sNewIndexName);
437 
438 		// update the user data on the entries in the list box:
439 		// they're iterators of the index collection, and thus they have changed when removing the index
440 		for (SvLBoxEntry* pAdjust = m_aIndexes.First(); pAdjust; pAdjust = m_aIndexes.Next(pAdjust))
441 		{
442 			Indexes::iterator aAfterInsertPos = m_pIndexes->find(m_aIndexes.GetEntryText(pAdjust));
443 			DBG_ASSERT(aAfterInsertPos != m_pIndexes->end(), "DbaIndexDialog::OnNewIndex: problems with on of the entries!");
444 			pAdjust->SetUserData(reinterpret_cast< void* >(sal_Int32(aAfterInsertPos - m_pIndexes->begin())));
445 		}
446 
447 		// select the entry and start in-place editing
448 		m_aIndexes.SelectNoHandlerCall(pNewEntry);
449 		OnIndexSelected(&m_aIndexes);
450 		m_aIndexes.EditEntry(pNewEntry);
451 		updateToolbox();
452 	}
453 
454 	//------------------------------------------------------------------
OnDropIndex(sal_Bool _bConfirm)455 	void DbaIndexDialog::OnDropIndex(sal_Bool _bConfirm)
456 	{
457 		// the selected index
458 		SvLBoxEntry* pSelected = m_aIndexes.FirstSelected();
459 		DBG_ASSERT(pSelected, "DbaIndexDialog::OnDropIndex: invalid call!");
460 		if (pSelected)
461 		{
462 			// let the user confirm the drop
463 			if (_bConfirm)
464 			{
465 				String sConfirm(ModuleRes(STR_CONFIRM_DROP_INDEX));
466 				sConfirm.SearchAndReplaceAscii("$name$", m_aIndexes.GetEntryText(pSelected));
467 				QueryBox aConfirm(this, WB_YES_NO, sConfirm);
468 				if (RET_YES != aConfirm.Execute())
469 					return;
470 			}
471 
472 			// do the drop
473 			implDropIndex(pSelected, sal_True);
474 
475 			// reflect the new selection in the toolbox
476 			updateToolbox();
477 		}
478 	}
479 
480 	//------------------------------------------------------------------
implDropIndex(SvLBoxEntry * _pEntry,sal_Bool _bRemoveFromCollection)481 	sal_Bool DbaIndexDialog::implDropIndex(SvLBoxEntry* _pEntry, sal_Bool _bRemoveFromCollection)
482 	{
483 		// do the drop
484 		Indexes::iterator aDropPos = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(_pEntry->GetUserData());
485 		DBG_ASSERT(aDropPos != m_pIndexes->end(), "DbaIndexDialog::OnDropIndex: did not find the index in my collection!");
486 
487 		SQLExceptionInfo aExceptionInfo;
488 		sal_Bool bSuccess = sal_False;
489 		try
490 		{
491 			if (_bRemoveFromCollection)
492 				bSuccess = m_pIndexes->drop(aDropPos);
493 			else
494 				bSuccess = m_pIndexes->dropNoRemove(aDropPos);
495 		}
496 		catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); }
497 		catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); }
498 		catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); }
499 
500 		if (aExceptionInfo.isValid())
501 			showError(aExceptionInfo, this, m_xORB);
502 		else if (bSuccess && _bRemoveFromCollection)
503 		{
504 			SvLBoxTreeList* pModel = m_aIndexes.GetModel();
505 
506 			m_aIndexes.disableSelectHandler();
507 			pModel->Remove(_pEntry);
508 			m_aIndexes.enableSelectHandler();
509 
510 			// update the user data on the entries in the list box:
511 			// they're iterators of the index collection, and thus they have changed when removing the index
512 			for (SvLBoxEntry* pAdjust = m_aIndexes.First(); pAdjust; pAdjust = m_aIndexes.Next(pAdjust))
513 			{
514 				Indexes::iterator aAfterDropPos = m_pIndexes->find(m_aIndexes.GetEntryText(pAdjust));
515 				DBG_ASSERT(aAfterDropPos != m_pIndexes->end(), "DbaIndexDialog::OnDropIndex: problems with on of the remaining entries!");
516 				pAdjust->SetUserData(reinterpret_cast< void* >(sal_Int32(aAfterDropPos - m_pIndexes->begin())));
517 			}
518 
519 			// if the remvoved entry was the selected on ...
520 			if (m_pPreviousSelection == _pEntry)
521 				m_pPreviousSelection = NULL;
522 
523 			// the Remove automatically selected another entry (if possible), but we disabled the calling of the handler
524 			// to prevent that we missed something ... call the handler directly
525 			OnIndexSelected(&m_aIndexes);
526 		}
527 
528 		return !aExceptionInfo.isValid();
529 	}
530 
531 	//------------------------------------------------------------------
OnRenameIndex()532 	void DbaIndexDialog::OnRenameIndex()
533 	{
534 		// the selected index
535 		SvLBoxEntry* pSelected = m_aIndexes.FirstSelected();
536 		DBG_ASSERT(pSelected, "DbaIndexDialog::OnRenameIndex: invalid call!");
537 
538 		// save the changes made 'til here
539 		// Upon leaving the edit mode, the control will be re-initialized with the
540 		// settings from the current entry
541 		implSaveModified(sal_False);
542 
543 		m_aIndexes.EditEntry(pSelected);
544 		updateToolbox();
545 	}
546 
547 	//------------------------------------------------------------------
OnSaveIndex()548 	void DbaIndexDialog::OnSaveIndex()
549 	{
550 		// the selected index
551 #if OSL_DEBUG_LEVEL > 0
552 		SvLBoxEntry* pSelected = m_aIndexes.FirstSelected();
553 		OSL_ENSURE( pSelected, "DbaIndexDialog::OnSaveIndex: invalid call!" );
554 #endif
555 
556 		implCommitPreviouslySelected();
557 		updateToolbox();
558 	}
559 
560 	//------------------------------------------------------------------
OnResetIndex()561 	void DbaIndexDialog::OnResetIndex()
562 	{
563 		// the selected index
564 		SvLBoxEntry* pSelected = m_aIndexes.FirstSelected();
565 		DBG_ASSERT(pSelected, "DbaIndexDialog::OnResetIndex: invalid call!");
566 
567 		Indexes::iterator aResetPos = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(pSelected->GetUserData());
568 
569 		if (aResetPos->isNew())
570 		{
571 			OnDropIndex(sal_False);
572 			return;
573 		}
574 
575 		SQLExceptionInfo aExceptionInfo;
576 		try
577 		{
578 			m_pIndexes->resetIndex(aResetPos);
579 		}
580 		catch(SQLContext& e) { aExceptionInfo = SQLExceptionInfo(e); }
581 		catch(SQLWarning& e) { aExceptionInfo = SQLExceptionInfo(e); }
582 		catch(SQLException& e) { aExceptionInfo = SQLExceptionInfo(e); }
583 
584 		if (aExceptionInfo.isValid())
585 			showError(aExceptionInfo, this, m_xORB);
586 		else
587 			m_aIndexes.SetEntryText(pSelected, aResetPos->sName);
588 
589 		updateControls(pSelected);
590 		updateToolbox();
591 	}
592 
593 	//------------------------------------------------------------------
594 	IMPL_LINK( DbaIndexDialog, OnIndexAction, ToolBox*, /*NOTINTERESTEDIN*/ )
595 	{
596 		sal_uInt16 nClicked = m_aActions.GetCurItemId();
597 		switch (nClicked)
598 		{
599 			case ID_INDEX_NEW:
600 				OnNewIndex();
601 				break;
602 			case ID_INDEX_DROP:
603 				OnDropIndex();
604 				break;
605 			case ID_INDEX_RENAME:
606 				OnRenameIndex();
607 				break;
608 			case ID_INDEX_SAVE:
609 				OnSaveIndex();
610 				break;
611 			case ID_INDEX_RESET:
612 				OnResetIndex();
613 				break;
614 		}
615 		return 0L;
616 	}
617 
618 	//------------------------------------------------------------------
619 	IMPL_LINK( DbaIndexDialog, OnCloseDialog, void*, /*NOTINTERESTEDIN*/ )
620 	{
621 		if (m_aIndexes.IsEditingActive())
622 		{
623 			DBG_ASSERT(!m_bEditAgain, "DbaIndexDialog::OnCloseDialog: somebody was faster than hell!");
624 				// this means somebody entered a new name, which was invalid, which cause us to posted us an event,
625 				// and before the event arrived the user clicked onto "close". VERY fast, this user ....
626 			m_aIndexes.EndEditing(sal_False);
627 			if (m_bEditAgain)
628 				// could not commit the new name (started a new - asynchronous - edit trial)
629 				return 1L;
630 		}
631 
632 		// the currently selected entry
633 		const SvLBoxEntry* pSelected = m_aIndexes.FirstSelected();
634 		DBG_ASSERT(pSelected == m_pPreviousSelection, "DbaIndexDialog::OnCloseDialog: inconsistence!");
635 
636 		sal_Int32 nResponse = RET_NO;
637 		if (pSelected)
638 		{
639 			// the descriptor
640 			Indexes::const_iterator aSelected = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(pSelected->GetUserData());
641 
642 			if (aSelected->isModified() || aSelected->isNew())
643 			{
644 				QueryBox aQuestion(this, ModuleRes(QUERY_SAVE_CURRENT_INDEX));
645 				nResponse = aQuestion.Execute();
646 			}
647 		}
648 
649 		switch (nResponse)
650 		{
651 			case RET_YES:
652 				if (!implCommitPreviouslySelected())
653 					return 1L;
654 				break;
655 			case RET_NO:
656 				break;
657 			default:
658 				return 1L;
659 		}
660 
661 		EndDialog(RET_OK);
662 
663 		return 0L;
664 	}
665 
666 	//------------------------------------------------------------------
IMPL_LINK(DbaIndexDialog,OnEditIndexAgain,SvLBoxEntry *,_pEntry)667 	IMPL_LINK( DbaIndexDialog, OnEditIndexAgain, SvLBoxEntry*, _pEntry )
668 	{
669 		m_bEditAgain = sal_False;
670 		m_aIndexes.EditEntry(_pEntry);
671 		return 0L;
672 	}
673 
674 	//------------------------------------------------------------------
IMPL_LINK(DbaIndexDialog,OnEntryEdited,SvLBoxEntry *,_pEntry)675 	IMPL_LINK( DbaIndexDialog, OnEntryEdited, SvLBoxEntry*, _pEntry )
676 	{
677 		Indexes::iterator aPosition = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(_pEntry->GetUserData());
678 
679 		DBG_ASSERT(aPosition >= m_pIndexes->begin() && aPosition < m_pIndexes->end(),
680 			"DbaIndexDialog::OnEntryEdited: invalid entry!");
681 
682 		String sNewName = m_aIndexes.GetEntryText(_pEntry);
683 
684 		Indexes::const_iterator aSameName = m_pIndexes->find(sNewName);
685 		if ((aSameName != aPosition) && (m_pIndexes->end() != aSameName))
686 		{
687 			String sError(ModuleRes(STR_INDEX_NAME_ALREADY_USED));
688 			sError.SearchAndReplaceAscii("$name$", sNewName);
689 			ErrorBox aError(this, WB_OK, sError);
690 			aError.Execute();
691 
692 			updateToolbox();
693 			m_bEditAgain = sal_True;
694 			PostUserEvent(LINK(this, DbaIndexDialog, OnEditIndexAgain), _pEntry);
695 			return 0L;
696 		}
697 
698 		aPosition->sName = sNewName;
699 
700 		// rename can be done by a drop/insert combination only
701 		if (aPosition->isNew())
702 		{
703 			updateToolbox();
704 			// no commitment needed here ....
705 			return 1L;
706 		}
707 
708 		if (aPosition->sName != aPosition->getOriginalName())
709 		{
710 			aPosition->setModified(sal_True);
711 			updateToolbox();
712 		}
713 
714 		return 1L;
715 	}
716 
717 	//------------------------------------------------------------------
implSaveModified(sal_Bool _bPlausibility)718 	sal_Bool DbaIndexDialog::implSaveModified(sal_Bool _bPlausibility)
719 	{
720 		if (m_pPreviousSelection)
721 		{
722 			// try to commit the previously selected index
723 			if (m_pFields->IsModified() && !m_pFields->SaveModified())
724 				return sal_False;
725 
726 			Indexes::iterator aPreviouslySelected = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(m_pPreviousSelection->GetUserData());
727 
728 			// the unique flag
729 			aPreviouslySelected->bUnique = m_aUnique.IsChecked();
730 			if (m_aUnique.GetSavedValue() != m_aUnique.GetState())
731 				aPreviouslySelected->setModified(sal_True);
732 
733 			// the fields
734 			m_pFields->commitTo(aPreviouslySelected->aFields);
735 			if (m_pFields->GetSavedValue() != aPreviouslySelected->aFields)
736 				aPreviouslySelected->setModified(sal_True);
737 
738 			// plausibility checks
739 			if (_bPlausibility && !implCheckPlausibility(aPreviouslySelected))
740 				return sal_False;
741 		}
742 
743 		return sal_True;
744 	}
745 
746 	//------------------------------------------------------------------
implCheckPlausibility(const ConstIndexesIterator & _rPos)747 	sal_Bool DbaIndexDialog::implCheckPlausibility(const ConstIndexesIterator& _rPos)
748 	{
749 		// need at least one field
750 		if (0 == _rPos->aFields.size())
751 		{
752 			ErrorBox aError(this, ModuleRes(ERR_NEED_INDEX_FIELDS));
753 			aError.Execute();
754 			m_pFields->GrabFocus();
755 			return sal_False;
756 		}
757 
758 		// no double fields
759 		DECLARE_STL_STDKEY_SET( String, StringBag );
760 		StringBag aExistentFields;
761 		for (	ConstIndexFieldsIterator aFieldCheck = _rPos->aFields.begin();
762 				aFieldCheck != _rPos->aFields.end();
763 				++aFieldCheck
764 			)
765 		{
766 			if (aExistentFields.end() != aExistentFields.find(aFieldCheck->sFieldName))
767 			{
768 				// a column is specified twice ... won't work anyway, so prevent this here and now
769 				String sMessage(ModuleRes(STR_INDEXDESIGN_DOUBLE_COLUMN_NAME));
770 				sMessage.SearchAndReplaceAscii("$name$", aFieldCheck->sFieldName);
771 				ErrorBox aError(this, WB_OK, sMessage);
772 				aError.Execute();
773 				m_pFields->GrabFocus();
774 				return sal_False;
775 			}
776 			aExistentFields.insert(aFieldCheck->sFieldName);
777 		}
778 
779 		return sal_True;
780 	}
781 
782 	//------------------------------------------------------------------
implCommitPreviouslySelected()783 	sal_Bool DbaIndexDialog::implCommitPreviouslySelected()
784 	{
785 		if (m_pPreviousSelection)
786 		{
787 			Indexes::iterator aPreviouslySelected = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(m_pPreviousSelection->GetUserData());
788 
789 			if (!implSaveModified())
790 				return sal_False;
791 
792 			// commit the index (if necessary)
793 			if (aPreviouslySelected->isModified() && !implCommit(m_pPreviousSelection))
794 				return sal_False;
795 		}
796 
797 		return sal_True;
798 	}
799 
800 	//------------------------------------------------------------------
801 	IMPL_LINK( DbaIndexDialog, OnModified, void*, /*NOTINTERESTEDIN*/ )
802 	{
803 		DBG_ASSERT(m_pPreviousSelection, "DbaIndexDialog, OnModified: invalid call!");
804 		Indexes::iterator aPosition = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(m_pPreviousSelection->GetUserData());
805 
806 		aPosition->setModified(sal_True);
807 		updateToolbox();
808 
809 		return 1L;
810 	}
811 
812 	//------------------------------------------------------------------
updateControls(const SvLBoxEntry * _pEntry)813 	void DbaIndexDialog::updateControls(const SvLBoxEntry* _pEntry)
814 	{
815 		if (_pEntry)
816 		{
817 			// the descriptor of the selected index
818 			Indexes::const_iterator aSelectedIndex = m_pIndexes->begin() + reinterpret_cast<sal_IntPtr>(_pEntry->GetUserData());
819 
820 			// fill the controls
821 			m_aUnique.Check(aSelectedIndex->bUnique);
822 			m_aUnique.Enable(!aSelectedIndex->bPrimaryKey);
823 			m_aUnique.SaveValue();
824 
825 			m_pFields->initializeFrom(aSelectedIndex->aFields);
826 			m_pFields->Enable(!aSelectedIndex->bPrimaryKey);
827 			m_pFields->SaveValue();
828 
829 			m_aDescription.SetText(aSelectedIndex->sDescription);
830 			m_aDescription.Enable(!aSelectedIndex->bPrimaryKey);
831 
832 			m_aDescriptionLabel.Enable(!aSelectedIndex->bPrimaryKey);
833 		}
834 		else
835 		{
836 			m_aUnique.Check(sal_False);
837 			m_pFields->initializeFrom(IndexFields());
838 			m_aDescription.SetText(String());
839 		}
840 	}
841 
842 	//------------------------------------------------------------------
843 	IMPL_LINK( DbaIndexDialog, OnIndexSelected, DbaIndexList*, /*NOTINTERESTEDIN*/ )
844 	{
845 		m_aIndexes.EndSelection();
846 
847 		if (m_aIndexes.IsEditingActive())
848 			m_aIndexes.EndEditing(sal_False);
849 
850 		// commit the old data
851 		if (m_aIndexes.FirstSelected() != m_pPreviousSelection)
852 		{	// (this call may happen in case somebody ended an in-place edit with 'return', so we need to check this before committing)
853 			if (!implCommitPreviouslySelected())
854 			{
855 				m_aIndexes.SelectNoHandlerCall(m_pPreviousSelection);
856 				return 1L;
857 			}
858 		}
859 
860 		sal_Bool bHaveSelection = (NULL != m_aIndexes.FirstSelected());
861 
862 		// disable/enable the detail controls
863 		m_aIndexDetails.Enable(bHaveSelection);
864 		m_aUnique.Enable(bHaveSelection);
865 		m_aDescriptionLabel.Enable(bHaveSelection);
866 		m_aFieldsLabel.Enable(bHaveSelection);
867 		m_pFields->Enable(bHaveSelection);
868 
869 		SvLBoxEntry* pNewSelection = m_aIndexes.FirstSelected();
870 		updateControls(pNewSelection);
871 		if (bHaveSelection)
872 			m_aIndexes.GrabFocus();
873 
874 		m_pPreviousSelection = pNewSelection;
875 
876 		updateToolbox();
877 		return 0L;
878 	}
879 	// -----------------------------------------------------------------------------
StateChanged(StateChangedType nType)880 	void DbaIndexDialog::StateChanged( StateChangedType nType )
881 	{
882 		ModalDialog::StateChanged( nType );
883 
884 		if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
885 		{
886 			// Check if we need to get new images for normal/high contrast mode
887 			checkImageList();
888 		}
889 		else if ( nType == STATE_CHANGE_TEXT )
890 		{
891 			// The physical toolbar changed its outlook and shows another logical toolbar!
892 			// We have to set the correct high contrast mode on the new tbx manager.
893 			//	pMgr->SetHiContrast( IsHiContrastMode() );
894 			checkImageList();
895 		}
896 	}
897 	// -----------------------------------------------------------------------------
DataChanged(const DataChangedEvent & rDCEvt)898 	void DbaIndexDialog::DataChanged( const DataChangedEvent& rDCEvt )
899 	{
900 		ModalDialog::DataChanged( rDCEvt );
901 
902 		if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS	)	||
903 			( rDCEvt.GetType() == DATACHANGED_DISPLAY	))	&&
904 			( rDCEvt.GetFlags() & SETTINGS_STYLE		))
905 		{
906 			// Check if we need to get new images for normal/high contrast mode
907 			checkImageList();
908 		}
909 	}
910 	//------------------------------------------------------------------
getImageList(sal_Int16 _eBitmapSet,sal_Bool _bHiContast) const911 	ImageList DbaIndexDialog::getImageList(sal_Int16 _eBitmapSet,sal_Bool _bHiContast) const
912 	{
913 		sal_Int16 nN = IMG_INDEX_DLG_SC;
914 		sal_Int16 nH = IMG_INDEX_DLG_SCH;
915 		if ( _eBitmapSet == SFX_SYMBOLS_SIZE_LARGE )
916 		{
917 			nN = IMG_INDEX_DLG_LC;
918 			nH = IMG_INDEX_DLG_LCH;
919 		} // if ( _eBitmapSet == SFX_SYMBOLS_LARGE )
920 		return ImageList(ModuleRes( _bHiContast ? nH : nN ));
921 	}
922 	//------------------------------------------------------------------
resizeControls(const Size & _rDiff)923 	void DbaIndexDialog::resizeControls(const Size& _rDiff)
924 	{
925 		// we use large images so we must change them
926 		Size aTbNewSize = m_aActions.GetSizePixel();
927 		if ( _rDiff.Width() || _rDiff.Height() )
928 		{
929 			Size aDlgSize = GetSizePixel();
930 			// adjust size of dlg
931 			SetSizePixel(Size(aDlgSize.Width() + _rDiff.Width(),
932 							  aDlgSize.Height() + _rDiff.Height())
933 						);
934 			Size aIndexSize = m_aIndexes.GetSizePixel();
935 			m_aIndexes.SetPosSizePixel(m_aIndexes.GetPosPixel() + Point(0,_rDiff.Height()),
936 									Size(aIndexSize.Width() + _rDiff.Width(),
937 										 aIndexSize.Height()));
938 
939 			// now move the rest to the left side
940 			Point aMove(_rDiff.Width(),_rDiff.Height());
941 			m_aIndexDetails.SetPosPixel(m_aIndexDetails.GetPosPixel() + aMove);
942 			m_aDescriptionLabel.SetPosPixel(m_aDescriptionLabel.GetPosPixel() + aMove);
943 			m_aDescription.SetPosPixel(m_aDescription.GetPosPixel() + aMove);
944 			m_aUnique.SetPosPixel(m_aUnique.GetPosPixel() + aMove);
945 			m_aFieldsLabel.SetPosPixel(m_aFieldsLabel.GetPosPixel() + aMove);
946 			OSL_ENSURE(m_pFields,"NO valid fields!");
947 			m_pFields->SetPosPixel(m_pFields->GetPosPixel() + aMove);
948 			m_aClose.SetPosPixel(m_aClose.GetPosPixel() + aMove);
949 			m_aHelp.SetPosPixel(m_aHelp.GetPosPixel() + aMove);
950 
951 			Invalidate();
952 		}
953 	}
954 
955 //......................................................................
956 }	// namespace dbaui
957 
958 /* vim: set noet sw=4 ts=4: */
959