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