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