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