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