xref: /AOO41X/main/dbaccess/source/ui/dlg/indexdialog.cxx (revision 96de54900b79e13b861fbc62cbf36018b54e21b7)
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_dbaccess.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 
959