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