Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "FieldDescriptions.hxx"
22 : #include "TEditControl.hxx"
23 : #include "TableController.hxx"
24 : #include "TableDesignView.hxx"
25 : #include "TableRow.hxx"
26 : #include "TypeInfo.hxx"
27 : #include "UITools.hxx"
28 : #include "browserids.hxx"
29 : #include "dbu_reghelper.hxx"
30 : #include "dbu_tbl.hrc"
31 : #include "dbustrings.hrc"
32 : #include "defaultobjectnamecheck.hxx"
33 : #include "dlgsave.hxx"
34 : #include "dsmeta.hxx"
35 : #include "indexdialog.hxx"
36 : #include "sqlmessage.hxx"
37 :
38 : #include <com/sun/star/container/XChild.hpp>
39 : #include <com/sun/star/container/XNameContainer.hpp>
40 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
41 : #include <com/sun/star/frame/XTitleChangeListener.hpp>
42 : #include <com/sun/star/frame/XUntitledNumbers.hpp>
43 : #include <com/sun/star/io/XActiveDataSink.hpp>
44 : #include <com/sun/star/io/XActiveDataSource.hpp>
45 : #include <com/sun/star/sdb/CommandType.hpp>
46 : #include <com/sun/star/sdb/SQLContext.hpp>
47 : #include <com/sun/star/sdbc/ColumnValue.hpp>
48 : #include <com/sun/star/sdbc/SQLWarning.hpp>
49 : #include <com/sun/star/sdbc/XRow.hpp>
50 : #include <com/sun/star/sdbcx/KeyType.hpp>
51 : #include <com/sun/star/sdbcx/XAlterTable.hpp>
52 : #include <com/sun/star/sdbcx/XAppend.hpp>
53 : #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
54 : #include <com/sun/star/sdbcx/XDrop.hpp>
55 : #include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
56 : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
57 : #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
58 :
59 : #include <comphelper/extract.hxx>
60 : #include <comphelper/processfactory.hxx>
61 : #include <comphelper/streamsection.hxx>
62 : #include <comphelper/types.hxx>
63 : #include <connectivity/dbexception.hxx>
64 : #include <connectivity/dbtools.hxx>
65 : #include <connectivity/dbmetadata.hxx>
66 : #include <cppuhelper/exc_hlp.hxx>
67 : #include <sfx2/sfxsids.hrc>
68 : #include <tools/diagnose_ex.h>
69 : #include <tools/string.hxx>
70 : #include <vcl/msgbox.hxx>
71 :
72 : #include <boost/mem_fn.hpp>
73 : #include <boost/bind.hpp>
74 :
75 : #include <algorithm>
76 : #include <functional>
77 :
78 0 : extern "C" void SAL_CALL createRegistryInfo_OTableControl()
79 : {
80 0 : static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OTableController > aAutoRegistration;
81 0 : }
82 :
83 : using namespace ::com::sun::star;
84 : using namespace ::com::sun::star::uno;
85 : using namespace ::com::sun::star::io;
86 : using namespace ::com::sun::star::beans;
87 : using namespace ::com::sun::star::frame;
88 : using namespace ::com::sun::star::util;
89 : using namespace ::com::sun::star::lang;
90 : using namespace ::com::sun::star::container;
91 : using namespace ::com::sun::star::sdbcx;
92 : using namespace ::com::sun::star::sdbc;
93 : using namespace ::com::sun::star::sdb;
94 : using namespace ::com::sun::star::ui;
95 : using namespace ::com::sun::star::util;
96 : using namespace ::dbtools;
97 : using namespace ::dbaui;
98 : using namespace ::comphelper;
99 :
100 : // Anzahl Spalten beim Neuanlegen
101 : #define NEWCOLS 128
102 :
103 : namespace
104 : {
105 0 : void dropTable(const Reference<XNameAccess>& _rxTable,const ::rtl::OUString& _sTableName)
106 : {
107 0 : if ( _rxTable->hasByName(_sTableName) )
108 : {
109 0 : Reference<XDrop> xNameCont(_rxTable,UNO_QUERY);
110 : OSL_ENSURE(xNameCont.is(),"No drop interface for tables!");
111 0 : if ( xNameCont.is() )
112 0 : xNameCont->dropByName(_sTableName);
113 : }
114 0 : }
115 : //------------------------------------------------------------------------------
116 : struct OTableRowCompare : public ::std::binary_function< ::boost::shared_ptr<OTableRow> , ::rtl::OUString, bool>
117 : {
118 : bool operator() (const ::boost::shared_ptr<OTableRow> lhs, const ::rtl::OUString& rhs) const
119 : {
120 : OFieldDescription* pField = lhs->GetActFieldDescr();
121 : return pField && pField->GetName() == rhs;
122 : }
123 : };
124 :
125 : }
126 :
127 : //------------------------------------------------------------------------------
128 0 : ::rtl::OUString SAL_CALL OTableController::getImplementationName() throw( RuntimeException )
129 : {
130 0 : return getImplementationName_Static();
131 : }
132 :
133 : //------------------------------------------------------------------------------
134 0 : ::rtl::OUString OTableController::getImplementationName_Static() throw( RuntimeException )
135 : {
136 0 : return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.dbu.OTableDesign"));
137 : }
138 : //------------------------------------------------------------------------------
139 0 : Sequence< ::rtl::OUString> OTableController::getSupportedServiceNames_Static(void) throw( RuntimeException )
140 : {
141 0 : Sequence< ::rtl::OUString> aSupported(1);
142 0 : aSupported.getArray()[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.TableDesign"));
143 0 : return aSupported;
144 : }
145 : //-------------------------------------------------------------------------
146 0 : Sequence< ::rtl::OUString> SAL_CALL OTableController::getSupportedServiceNames() throw(RuntimeException)
147 : {
148 0 : return getSupportedServiceNames_Static();
149 : }
150 : // -------------------------------------------------------------------------
151 0 : Reference< XInterface > SAL_CALL OTableController::Create(const Reference<XMultiServiceFactory >& _rxFactory)
152 : {
153 0 : return *(new OTableController(_rxFactory));
154 : }
155 :
156 : DBG_NAME(OTableController)
157 : // -----------------------------------------------------------------------------
158 0 : OTableController::OTableController(const Reference< XMultiServiceFactory >& _rM) : OTableController_BASE(_rM)
159 : ,m_sTypeNames(ModuleRes(STR_TABLEDESIGN_DBFIELDTYPES))
160 : ,m_pTypeInfo()
161 : ,m_bAllowAutoIncrementValue(sal_False)
162 0 : ,m_bNew(sal_True)
163 : {
164 : DBG_CTOR(OTableController,NULL);
165 :
166 0 : InvalidateAll();
167 0 : m_pTypeInfo = TOTypeInfoSP(new OTypeInfo());
168 0 : m_pTypeInfo->aUIName = m_sTypeNames.GetToken(TYPE_OTHER);
169 0 : }
170 : // -----------------------------------------------------------------------------
171 0 : OTableController::~OTableController()
172 : {
173 0 : m_aTypeInfoIndex.clear();
174 0 : m_aTypeInfo.clear();
175 :
176 : DBG_DTOR(OTableController,NULL);
177 0 : }
178 :
179 : // -----------------------------------------------------------------------------
180 0 : void OTableController::startTableListening()
181 : {
182 0 : Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
183 0 : if (xComponent.is())
184 0 : xComponent->addEventListener(static_cast<XModifyListener*>(this));
185 0 : }
186 :
187 : // -----------------------------------------------------------------------------
188 0 : void OTableController::stopTableListening()
189 : {
190 0 : Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
191 0 : if (xComponent.is())
192 0 : xComponent->removeEventListener(static_cast<XModifyListener*>(this));
193 0 : }
194 :
195 : // -----------------------------------------------------------------------------
196 0 : void OTableController::disposing()
197 : {
198 0 : OTableController_BASE::disposing();
199 0 : clearView();
200 :
201 0 : m_vRowList.clear();
202 0 : }
203 : // -----------------------------------------------------------------------------
204 0 : FeatureState OTableController::GetState(sal_uInt16 _nId) const
205 : {
206 0 : FeatureState aReturn;
207 : // (disabled automatically)
208 :
209 0 : switch (_nId)
210 : {
211 : case ID_BROWSER_CLOSE:
212 0 : aReturn.bEnabled = sal_True;
213 0 : break;
214 : case ID_BROWSER_EDITDOC:
215 0 : aReturn.bChecked = isEditable();
216 0 : aReturn.bEnabled = m_bNew || isEditable();// the editable flag is set through this one -> || isAddAllowed() || isDropAllowed() || isAlterAllowed();
217 0 : break;
218 : case ID_BROWSER_SAVEDOC:
219 0 : aReturn.bEnabled = impl_isModified();
220 0 : if ( aReturn.bEnabled )
221 : {
222 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter = ::std::find_if(m_vRowList.begin(),m_vRowList.end(),
223 0 : ::boost::mem_fn(&OTableRow::isValid));
224 0 : aReturn.bEnabled = aIter != m_vRowList.end();
225 : }
226 0 : break;
227 : case ID_BROWSER_SAVEASDOC:
228 0 : aReturn.bEnabled = isConnected() && isEditable();
229 0 : if ( aReturn.bEnabled )
230 : {
231 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter = ::std::find_if(m_vRowList.begin(),m_vRowList.end(),
232 0 : ::boost::mem_fn(&OTableRow::isValid));
233 0 : aReturn.bEnabled = aIter != m_vRowList.end();
234 : }
235 0 : break;
236 :
237 : case ID_BROWSER_CUT:
238 0 : aReturn.bEnabled = isEditable() && m_aCurrentFrame.isActive() && getView() && static_cast<OTableDesignView*>(getView())->isCutAllowed();
239 0 : break;
240 : case ID_BROWSER_COPY:
241 0 : aReturn.bEnabled = m_aCurrentFrame.isActive() && getView() && static_cast<OTableDesignView*>(getView())->isCopyAllowed();
242 0 : break;
243 : case ID_BROWSER_PASTE:
244 0 : aReturn.bEnabled = isEditable() && m_aCurrentFrame.isActive() && getView() && static_cast<OTableDesignView*>(getView())->isPasteAllowed();
245 0 : break;
246 : case SID_INDEXDESIGN:
247 : aReturn.bEnabled =
248 0 : ( ( ((!m_bNew && impl_isModified()) || impl_isModified())
249 0 : || Reference< XIndexesSupplier >(m_xTable, UNO_QUERY).is()
250 : )
251 0 : && isConnected()
252 0 : );
253 0 : if ( aReturn.bEnabled )
254 : {
255 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter = ::std::find_if(m_vRowList.begin(),m_vRowList.end(),
256 0 : ::boost::mem_fn(&OTableRow::isValid));
257 0 : aReturn.bEnabled = aIter != m_vRowList.end();
258 : }
259 0 : break;
260 : default:
261 0 : aReturn = OTableController_BASE::GetState(_nId);
262 : }
263 0 : return aReturn;
264 : }
265 : // -----------------------------------------------------------------------------
266 0 : void OTableController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
267 : {
268 0 : switch(_nId)
269 : {
270 : case ID_BROWSER_EDITDOC:
271 0 : setEditable(!isEditable());
272 0 : static_cast<OTableDesignView*>(getView())->setReadOnly(!isEditable());
273 0 : InvalidateFeature(ID_BROWSER_PASTE);
274 0 : InvalidateFeature(SID_BROWSER_CLEAR_QUERY);
275 0 : break;
276 : case ID_BROWSER_SAVEASDOC:
277 0 : doSaveDoc(sal_True);
278 0 : break;
279 : case ID_BROWSER_SAVEDOC:
280 0 : static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->SaveCurRow();
281 0 : doSaveDoc(sal_False);
282 0 : break;
283 : case ID_BROWSER_CUT:
284 0 : static_cast<OTableDesignView*>(getView())->cut();
285 0 : break;
286 : case ID_BROWSER_COPY:
287 0 : static_cast<OTableDesignView*>(getView())->copy();
288 0 : break;
289 : case ID_BROWSER_PASTE:
290 0 : static_cast<OTableDesignView*>(getView())->paste();
291 0 : break;
292 : case SID_INDEXDESIGN:
293 0 : doEditIndexes();
294 0 : break;
295 : default:
296 0 : OTableController_BASE::Execute(_nId,aArgs);
297 : }
298 0 : InvalidateFeature(_nId);
299 0 : }
300 :
301 : // -----------------------------------------------------------------------------
302 0 : sal_Bool OTableController::doSaveDoc(sal_Bool _bSaveAs)
303 : {
304 0 : if (!isConnected())
305 0 : reconnect(sal_True); // ask the user for a new connection
306 0 : Reference<XTablesSupplier> xTablesSup(getConnection(),UNO_QUERY);
307 :
308 0 : if (!xTablesSup.is())
309 : {
310 0 : String aMessage(ModuleRes(STR_TABLEDESIGN_CONNECTION_MISSING));
311 0 : OSQLWarningBox( getView(), aMessage ).Execute();
312 0 : return sal_False;
313 : }
314 :
315 : // check if a column exists
316 : // TODO
317 :
318 0 : Reference<XNameAccess> xTables;
319 0 : ::rtl::OUString sCatalog, sSchema;
320 :
321 0 : sal_Bool bNew = m_sName.isEmpty();
322 0 : bNew = bNew || m_bNew || _bSaveAs;
323 :
324 : try
325 : {
326 0 : xTables = xTablesSup->getTables();
327 : OSL_ENSURE(xTables.is(),"The tables can't be null!");
328 0 : bNew = bNew || (xTables.is() && !xTables->hasByName(m_sName));
329 :
330 : // first we need a name for our query so ask the user
331 0 : if(bNew)
332 : {
333 0 : String aDefaultName;
334 0 : if (_bSaveAs && !bNew)
335 0 : aDefaultName = String(m_sName);
336 : else
337 : {
338 0 : String aName = String(ModuleRes(STR_TBL_TITLE));
339 0 : aDefaultName = aName.GetToken(0,' ');
340 0 : aDefaultName = ::dbtools::createUniqueName(xTables,aDefaultName);
341 : }
342 :
343 0 : DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::TABLE );
344 0 : OSaveAsDlg aDlg( getView(), CommandType::TABLE, comphelper::getComponentContext(getORB()), getConnection(), aDefaultName, aNameChecker );
345 0 : if ( aDlg.Execute() != RET_OK )
346 0 : return sal_False;
347 :
348 0 : m_sName = aDlg.getName();
349 0 : sCatalog = aDlg.getCatalog();
350 0 : sSchema = aDlg.getSchema();
351 : }
352 :
353 : // did we get a name
354 0 : if(m_sName.isEmpty())
355 0 : return sal_False;
356 : }
357 0 : catch(Exception&)
358 : {
359 : OSL_FAIL("OTableController::doSaveDoc: nothing is expected to happen here!");
360 : }
361 :
362 0 : sal_Bool bAlter = sal_False;
363 0 : sal_Bool bError = sal_False;
364 0 : SQLExceptionInfo aInfo;
365 : try
366 : {
367 : // check the columns for double names
368 0 : if(!checkColumns(bNew || !xTables->hasByName(m_sName)))
369 : {
370 0 : return sal_False;
371 : }
372 :
373 0 : Reference<XPropertySet> xTable;
374 0 : if(bNew || !xTables->hasByName(m_sName)) // just to make sure the table already exists
375 : {
376 0 : dropTable(xTables,m_sName);
377 :
378 0 : Reference<XDataDescriptorFactory> xFact(xTables,UNO_QUERY);
379 : OSL_ENSURE(xFact.is(),"OTableController::doSaveDoc: No XDataDescriptorFactory available!");
380 0 : xTable = xFact->createDataDescriptor();
381 : OSL_ENSURE(xTable.is(),"OTableController::doSaveDoc: Create query failed!");
382 : // to set the name is only allowed when the wuery is new
383 0 : xTable->setPropertyValue(PROPERTY_CATALOGNAME,makeAny(sCatalog));
384 0 : xTable->setPropertyValue(PROPERTY_SCHEMANAME,makeAny(sSchema));
385 0 : xTable->setPropertyValue(PROPERTY_NAME,makeAny(m_sName));
386 :
387 : // now append the columns
388 0 : Reference<XColumnsSupplier> xColSup(xTable,UNO_QUERY);
389 0 : appendColumns(xColSup,bNew);
390 : // now append the primary key
391 0 : Reference<XKeysSupplier> xKeySup(xTable,UNO_QUERY);
392 0 : appendPrimaryKey(xKeySup,bNew);
393 : }
394 : // now set the properties
395 0 : if(bNew)
396 : {
397 0 : Reference<XAppend> xAppend(xTables,UNO_QUERY);
398 : OSL_ENSURE(xAppend.is(),"OTableController::doSaveDoc: No XAppend Interface!");
399 0 : xAppend->appendByDescriptor(xTable);
400 :
401 0 : assignTable();
402 0 : if(!m_xTable.is()) // correct name and try again
403 : {
404 : // it can be that someone inserted new data for us
405 0 : m_sName = ::dbtools::composeTableName( getConnection()->getMetaData(), xTable, ::dbtools::eInDataManipulation, false, false, false );
406 0 : assignTable();
407 : }
408 : // now check if our datasource has set a tablefilter and if append the new table name to it
409 0 : ::dbaui::appendToFilter(getConnection(),m_sName,comphelper::getComponentContext(getORB()),getView()); // we are not interessted in the return value
410 0 : Reference< frame::XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY);
411 0 : if ( xEventListener.is() )
412 : {
413 0 : frame::TitleChangedEvent aEvent;
414 0 : xEventListener->titleChanged(aEvent);
415 : }
416 0 : releaseNumberForComponent();
417 : }
418 0 : else if(m_xTable.is())
419 : {
420 0 : bAlter = sal_True;
421 0 : alterColumns();
422 : }
423 0 : reSyncRows();
424 : }
425 0 : catch(const SQLContext& e)
426 : {
427 0 : aInfo = SQLExceptionInfo(e);
428 : }
429 0 : catch(const SQLWarning& e)
430 : {
431 0 : aInfo = SQLExceptionInfo(e);
432 : }
433 0 : catch(const SQLException& e)
434 : {
435 0 : aInfo = SQLExceptionInfo(e);
436 : }
437 0 : catch(const ElementExistException& )
438 : {
439 0 : String sText( ModuleRes( STR_NAME_ALREADY_EXISTS ) );
440 0 : sText.SearchAndReplaceAscii( "#" , m_sName);
441 0 : OSQLMessageBox aDlg( getView(), String( ModuleRes( STR_ERROR_DURING_CREATION ) ), sText, WB_OK, OSQLMessageBox::Error );
442 :
443 0 : aDlg.Execute();
444 0 : bError = sal_True;
445 : }
446 0 : catch( const Exception& )
447 : {
448 0 : bError = sal_True;
449 : DBG_UNHANDLED_EXCEPTION();
450 : }
451 :
452 0 : if ( aInfo.isValid() )
453 0 : aInfo.prepend( String( ModuleRes( STR_TABLEDESIGN_SAVE_ERROR ) ) );
454 0 : showError(aInfo);
455 :
456 0 : if (aInfo.isValid() || bError)
457 : {
458 0 : if(!bAlter || bNew)
459 : {
460 0 : m_sName = ::rtl::OUString();
461 0 : stopTableListening();
462 0 : m_xTable = NULL;
463 : }
464 : }
465 0 : return ! (aInfo.isValid() || bError);
466 : }
467 :
468 : // -----------------------------------------------------------------------------
469 0 : void OTableController::doEditIndexes()
470 : {
471 : // table needs to be saved before editing indexes
472 0 : if (m_bNew || isModified())
473 : {
474 0 : QueryBox aAsk(getView(), ModuleRes(QUERY_SAVE_TABLE_EDIT_INDEXES));
475 0 : if (RET_YES != aAsk.Execute())
476 : return;
477 :
478 0 : if (!doSaveDoc(sal_False))
479 : return;
480 :
481 0 : OSL_ENSURE(!m_bNew && !isModified(), "OTableController::doEditIndexes: what the hell did doSaveDoc do?");
482 : }
483 :
484 0 : Reference< XNameAccess > xIndexes; // will be the keys of the table
485 0 : Sequence< ::rtl::OUString > aFieldNames; // will be the column names of the table
486 : try
487 : {
488 : // get the keys
489 0 : Reference< XIndexesSupplier > xIndexesSupp(m_xTable, UNO_QUERY);
490 0 : if (xIndexesSupp.is())
491 : {
492 0 : xIndexes = xIndexesSupp->getIndexes();
493 : OSL_ENSURE(xIndexes.is(), "OTableController::doEditIndexes: no keys got from the indexes supplier!");
494 : }
495 : else
496 : OSL_FAIL("OTableController::doEditIndexes: should never have reached this (no indexes supplier)!");
497 :
498 : // get the field names
499 0 : Reference< XColumnsSupplier > xColSupp(m_xTable, UNO_QUERY);
500 : OSL_ENSURE(xColSupp.is(), "OTableController::doEditIndexes: no columns supplier!");
501 0 : if (xColSupp.is())
502 : {
503 0 : Reference< XNameAccess > xCols = xColSupp->getColumns();
504 : OSL_ENSURE(xCols.is(), "OTableController::doEditIndexes: no columns!");
505 0 : if (xCols.is())
506 0 : aFieldNames = xCols->getElementNames();
507 0 : }
508 : }
509 0 : catch( const Exception& )
510 : {
511 : DBG_UNHANDLED_EXCEPTION();
512 : }
513 :
514 0 : if (!xIndexes.is())
515 : return;
516 :
517 0 : DbaIndexDialog aDialog(getView(), aFieldNames, xIndexes, getConnection(), comphelper::getComponentContext(getORB()), isConnected() ? getConnection()->getMetaData().is() && getConnection()->getMetaData()->getMaxColumnsInIndex() : sal_Int32(0));
518 0 : if (RET_OK != aDialog.Execute())
519 0 : return;
520 :
521 : }
522 :
523 : // -----------------------------------------------------------------------------
524 0 : void OTableController::impl_initialize()
525 : {
526 : try
527 : {
528 0 : OTableController_BASE::impl_initialize();
529 :
530 0 : const NamedValueCollection& rArguments( getInitParams() );
531 :
532 0 : rArguments.get_ensureType( (::rtl::OUString)PROPERTY_CURRENTTABLE, m_sName );
533 :
534 : // read autoincrement value set in the datasource
535 0 : ::dbaui::fillAutoIncrementValue(getDataSource(),m_bAllowAutoIncrementValue,m_sAutoIncrementValue);
536 :
537 0 : assignTable();
538 : }
539 0 : catch( const Exception& )
540 : {
541 : DBG_UNHANDLED_EXCEPTION();
542 : }
543 :
544 : try
545 : {
546 0 : ::dbaui::fillTypeInfo(getConnection(),m_sTypeNames,m_aTypeInfo,m_aTypeInfoIndex); // fill the needed type information
547 : }
548 0 : catch(const SQLException&)
549 : {
550 0 : OSQLWarningBox( getView(), ModuleRes( STR_NO_TYPE_INFO_AVAILABLE ) ).Execute();
551 0 : throw;
552 : }
553 : try
554 : {
555 0 : loadData(); // fill the column information form the table
556 0 : getView()->initialize(); // show the windows and fill with our informations
557 0 : ClearUndoManager();
558 0 : setModified(sal_False); // and we are not modified yet
559 : }
560 0 : catch( const Exception& )
561 : {
562 : DBG_UNHANDLED_EXCEPTION();
563 : }
564 0 : }
565 : // -----------------------------------------------------------------------------
566 0 : sal_Bool OTableController::Construct(Window* pParent)
567 : {
568 0 : setView( * new OTableDesignView( pParent, comphelper::getComponentContext(getORB()), *this ) );
569 0 : OTableController_BASE::Construct(pParent);
570 0 : return sal_True;
571 : }
572 : // -----------------------------------------------------------------------------
573 0 : sal_Bool SAL_CALL OTableController::suspend(sal_Bool /*_bSuspend*/) throw( RuntimeException )
574 : {
575 0 : if ( getBroadcastHelper().bInDispose || getBroadcastHelper().bDisposed )
576 0 : return sal_True;
577 :
578 0 : SolarMutexGuard aSolarGuard;
579 0 : ::osl::MutexGuard aGuard( getMutex() );
580 0 : if ( getView() && getView()->IsInModalMode() )
581 0 : return sal_False;
582 0 : if ( getView() )
583 0 : static_cast<OTableDesignView*>(getView())->GrabFocus();
584 0 : sal_Bool bCheck = sal_True;
585 0 : if ( isModified() )
586 : {
587 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aIter = ::std::find_if(m_vRowList.begin(),m_vRowList.end(),
588 0 : ::boost::mem_fn(&OTableRow::isValid));
589 0 : if ( aIter != m_vRowList.end() )
590 : {
591 0 : QueryBox aQry(getView(), ModuleRes(TABLE_DESIGN_SAVEMODIFIED));
592 0 : switch (aQry.Execute())
593 : {
594 : case RET_YES:
595 0 : Execute(ID_BROWSER_SAVEDOC,Sequence<PropertyValue>());
596 0 : if ( isModified() )
597 0 : bCheck = sal_False; // when we save the table this must be false else some press cancel
598 0 : break;
599 : case RET_CANCEL:
600 0 : bCheck = sal_False;
601 : default:
602 0 : break;
603 0 : }
604 : }
605 0 : else if ( !m_bNew )
606 : {
607 0 : QueryBox aQry(getView(), ModuleRes(TABLE_DESIGN_ALL_ROWS_DELETED));
608 0 : switch (aQry.Execute())
609 : {
610 : case RET_YES:
611 : {
612 : try
613 : {
614 0 : Reference<XTablesSupplier> xTablesSup(getConnection(),UNO_QUERY);
615 0 : Reference<XNameAccess> xTables = xTablesSup->getTables();
616 0 : dropTable(xTables,m_sName);
617 : }
618 0 : catch(const Exception&)
619 : {
620 : OSL_FAIL("OTableController::suspend: nothing is expected to happen here!");
621 : }
622 :
623 : }
624 0 : break;
625 : case RET_CANCEL:
626 0 : bCheck = sal_False;
627 : default:
628 0 : break;
629 0 : }
630 : }
631 : }
632 :
633 0 : return bCheck;
634 : }
635 : // -----------------------------------------------------------------------------
636 0 : void OTableController::describeSupportedFeatures()
637 : {
638 0 : OSingleDocumentController::describeSupportedFeatures();
639 :
640 0 : implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO, CommandGroup::EDIT );
641 0 : implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC, CommandGroup::EDIT );
642 0 : implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO, CommandGroup::EDIT );
643 0 : implDescribeSupportedFeature( ".uno:HelpMenu", SID_HELPMENU, CommandGroup::APPLICATION );
644 0 : implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC, CommandGroup::DOCUMENT );
645 0 : implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT );
646 0 : implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN, CommandGroup::APPLICATION );
647 0 : implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC, CommandGroup::EDIT );
648 0 : }
649 : // -----------------------------------------------------------------------------
650 0 : void OTableController::impl_onModifyChanged()
651 : {
652 0 : OSingleDocumentController::impl_onModifyChanged();
653 0 : InvalidateFeature( SID_INDEXDESIGN );
654 0 : }
655 : // -----------------------------------------------------------------------------
656 0 : void SAL_CALL OTableController::disposing( const EventObject& _rSource ) throw(RuntimeException)
657 : {
658 0 : if ( _rSource.Source == m_xTable )
659 : { // some deleted our table so we have a new one
660 0 : stopTableListening();
661 0 : m_xTable = NULL;
662 0 : m_bNew = sal_True;
663 0 : setModified(sal_True);
664 : }
665 : else
666 0 : OTableController_BASE::disposing( _rSource );
667 0 : }
668 : // -----------------------------------------------------------------------------
669 0 : void OTableController::Save(const Reference< XObjectOutputStream>& _rxOut)
670 : {
671 0 : OStreamSection aSection(_rxOut.get());
672 :
673 0 : }
674 : // -----------------------------------------------------------------------------
675 0 : void OTableController::Load(const Reference< XObjectInputStream>& _rxIn)
676 : {
677 0 : OStreamSection aSection(_rxIn.get());
678 0 : }
679 :
680 : // -----------------------------------------------------------------------------
681 0 : void OTableController::losingConnection( )
682 : {
683 : // let the base class do it's reconnect
684 0 : OTableController_BASE::losingConnection( );
685 :
686 : // remove from the table
687 0 : Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
688 0 : if (xComponent.is())
689 : {
690 0 : Reference<XEventListener> xEvtL( static_cast< ::cppu::OWeakObject*>(this), UNO_QUERY);
691 0 : xComponent->removeEventListener(xEvtL);
692 : }
693 0 : stopTableListening();
694 0 : m_xTable = NULL;
695 0 : assignTable();
696 0 : if(!m_xTable.is())
697 : {
698 0 : m_bNew = sal_True;
699 0 : setModified(sal_True);
700 : }
701 0 : InvalidateAll();
702 0 : }
703 : // -----------------------------------------------------------------------------
704 0 : TOTypeInfoSP OTableController::getTypeInfoByType(sal_Int32 _nDataType) const
705 : {
706 0 : return queryTypeInfoByType(_nDataType,m_aTypeInfo);
707 : }
708 : // -----------------------------------------------------------------------------
709 0 : void OTableController::appendColumns(Reference<XColumnsSupplier>& _rxColSup,sal_Bool _bNew,sal_Bool _bKeyColumns)
710 : {
711 : try
712 : {
713 : // now append the columns
714 : OSL_ENSURE(_rxColSup.is(),"No columns supplier");
715 0 : if(!_rxColSup.is())
716 0 : return;
717 0 : Reference<XNameAccess> xColumns = _rxColSup->getColumns();
718 : OSL_ENSURE(xColumns.is(),"No columns");
719 0 : Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY);
720 :
721 0 : Reference<XAppend> xAppend(xColumns,UNO_QUERY);
722 : OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
723 :
724 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aIter = m_vRowList.begin();
725 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aEnd = m_vRowList.end();
726 0 : for(;aIter != aEnd;++aIter)
727 : {
728 : OSL_ENSURE(*aIter,"OTableRow is null!");
729 0 : OFieldDescription* pField = (*aIter)->GetActFieldDescr();
730 0 : if ( !pField || (!_bNew && (*aIter)->IsReadOnly() && !_bKeyColumns) )
731 0 : continue;
732 :
733 0 : Reference<XPropertySet> xColumn;
734 0 : if(pField->IsPrimaryKey() || !_bKeyColumns)
735 0 : xColumn = xColumnFactory->createDataDescriptor();
736 0 : if(xColumn.is())
737 : {
738 0 : if(!_bKeyColumns)
739 0 : ::dbaui::setColumnProperties(xColumn,pField);
740 : else
741 0 : xColumn->setPropertyValue(PROPERTY_NAME,makeAny(pField->GetName()));
742 :
743 0 : xAppend->appendByDescriptor(xColumn);
744 0 : xColumn = NULL;
745 : // now only the settings are missing
746 0 : if(xColumns->hasByName(pField->GetName()))
747 : {
748 0 : xColumns->getByName(pField->GetName()) >>= xColumn;
749 0 : if(xColumn.is())
750 0 : pField->copyColumnSettingsTo(xColumn);
751 : }
752 : else
753 : {
754 : OSL_FAIL("OTableController::appendColumns: invalid field name!");
755 : }
756 :
757 : }
758 0 : }
759 : }
760 0 : catch(const SQLException& )
761 : {
762 0 : showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
763 : }
764 0 : catch( const Exception& )
765 : {
766 : DBG_UNHANDLED_EXCEPTION();
767 : }
768 : }
769 : // -----------------------------------------------------------------------------
770 0 : void OTableController::appendPrimaryKey(Reference<XKeysSupplier>& _rxSup,sal_Bool _bNew)
771 : {
772 0 : if(!_rxSup.is())
773 : return; // the database doesn't support keys
774 :
775 : OSL_ENSURE(_rxSup.is(),"No XKeysSupplier!");
776 0 : Reference<XIndexAccess> xKeys(_rxSup->getKeys(),UNO_QUERY);
777 0 : Reference<XPropertySet> xProp;
778 0 : const sal_Int32 nCount = xKeys->getCount();
779 0 : for(sal_Int32 i=0;i< nCount ;++i)
780 : {
781 0 : xKeys->getByIndex(i) >>= xProp;
782 0 : sal_Int32 nKeyType = 0;
783 0 : xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
784 0 : if(KeyType::PRIMARY == nKeyType)
785 : {
786 : return; // primary key already exists after appending a column
787 : }
788 : }
789 0 : Reference<XDataDescriptorFactory> xKeyFactory(xKeys,UNO_QUERY);
790 : OSL_ENSURE(xKeyFactory.is(),"No XDataDescriptorFactory Interface!");
791 0 : if ( !xKeyFactory.is() )
792 : return;
793 0 : Reference<XAppend> xAppend(xKeyFactory,UNO_QUERY);
794 : OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
795 :
796 0 : Reference<XPropertySet> xKey = xKeyFactory->createDataDescriptor();
797 : OSL_ENSURE(xKey.is(),"Key is null!");
798 0 : xKey->setPropertyValue(PROPERTY_TYPE,makeAny(KeyType::PRIMARY));
799 :
800 0 : Reference<XColumnsSupplier> xColSup(xKey,UNO_QUERY);
801 0 : if(xColSup.is())
802 : {
803 0 : appendColumns(xColSup,_bNew,sal_True);
804 0 : Reference<XNameAccess> xColumns = xColSup->getColumns();
805 0 : if(xColumns->hasElements())
806 0 : xAppend->appendByDescriptor(xKey);
807 0 : }
808 : }
809 : // -----------------------------------------------------------------------------
810 0 : void OTableController::loadData()
811 : {
812 : //////////////////////////////////////////////////////////////////////
813 : // Wenn Datenstruktur bereits vorhanden, Struktur leeren
814 0 : m_vRowList.clear();
815 :
816 0 : ::boost::shared_ptr<OTableRow> pTabEdRow;
817 0 : Reference< XDatabaseMetaData> xMetaData = getMetaData( );
818 : //////////////////////////////////////////////////////////////////////
819 : // Datenstruktur mit Daten aus DatenDefinitionsObjekt fuellen
820 0 : if(m_xTable.is() && xMetaData.is())
821 : {
822 0 : Reference<XColumnsSupplier> xColSup(m_xTable,UNO_QUERY);
823 : OSL_ENSURE(xColSup.is(),"No XColumnsSupplier!");
824 0 : Reference<XNameAccess> xColumns = xColSup->getColumns();
825 0 : OFieldDescription* pActFieldDescr = NULL;
826 0 : String aType;
827 : //////////////////////////////////////////////////////////////////////
828 : // ReadOnly-Flag
829 : // Bei Drop darf keine Zeile editierbar sein.
830 : // Bei Add duerfen nur die leeren Zeilen editierbar sein.
831 : // Bei Add und Drop koennen alle Zeilen editiert werden.
832 : // sal_Bool bReadOldRow = xMetaData->supportsAlterTableWithAddColumn() && xMetaData->supportsAlterTableWithDropColumn();
833 0 : sal_Bool bIsAlterAllowed = isAlterAllowed();
834 0 : Sequence< ::rtl::OUString> aColumns = xColumns->getElementNames();
835 0 : const ::rtl::OUString* pIter = aColumns.getConstArray();
836 0 : const ::rtl::OUString* pEnd = pIter + aColumns.getLength();
837 :
838 0 : for(;pIter != pEnd;++pIter)
839 : {
840 0 : Reference<XPropertySet> xColumn;
841 0 : xColumns->getByName(*pIter) >>= xColumn;
842 0 : sal_Int32 nType = 0;
843 0 : sal_Int32 nScale = 0;
844 0 : sal_Int32 nPrecision = 0;
845 0 : sal_Int32 nNullable = 0;
846 0 : sal_Int32 nFormatKey = 0;
847 0 : sal_Int32 nAlign = 0;
848 :
849 0 : sal_Bool bIsAutoIncrement = false, bIsCurrency = false;
850 0 : ::rtl::OUString sName,sDescription,sTypeName,sHelpText;
851 0 : Any aControlDefault;
852 :
853 : // get the properties from the column
854 0 : xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
855 0 : xColumn->getPropertyValue(PROPERTY_TYPENAME) >>= sTypeName;
856 0 : xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable;
857 0 : xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT) >>= bIsAutoIncrement;
858 0 : xColumn->getPropertyValue(PROPERTY_ISCURRENCY) >>= bIsCurrency;
859 0 : xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType;
860 0 : xColumn->getPropertyValue(PROPERTY_SCALE) >>= nScale;
861 0 : xColumn->getPropertyValue(PROPERTY_PRECISION) >>= nPrecision;
862 0 : xColumn->getPropertyValue(PROPERTY_DESCRIPTION) >>= sDescription;
863 :
864 0 : if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_HELPTEXT))
865 0 : xColumn->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
866 :
867 0 : if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_CONTROLDEFAULT))
868 0 : aControlDefault = xColumn->getPropertyValue(PROPERTY_CONTROLDEFAULT);
869 0 : if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_FORMATKEY))
870 0 : xColumn->getPropertyValue(PROPERTY_FORMATKEY) >>= nFormatKey;
871 0 : if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_ALIGN))
872 0 : xColumn->getPropertyValue(PROPERTY_ALIGN) >>= nAlign;
873 :
874 0 : pTabEdRow.reset(new OTableRow());
875 0 : pTabEdRow->SetReadOnly(!bIsAlterAllowed);
876 : // search for type
877 : sal_Bool bForce;
878 0 : ::rtl::OUString sCreate(RTL_CONSTASCII_USTRINGPARAM("x"));
879 0 : TOTypeInfoSP pTypeInfo = ::dbaui::getTypeInfoFromType(m_aTypeInfo,nType,sTypeName,sCreate,nPrecision,nScale,bIsAutoIncrement,bForce);
880 0 : if ( !pTypeInfo.get() )
881 0 : pTypeInfo = m_pTypeInfo;
882 0 : pTabEdRow->SetFieldType( pTypeInfo, bForce );
883 :
884 0 : pActFieldDescr = pTabEdRow->GetActFieldDescr();
885 : OSL_ENSURE(pActFieldDescr, "OTableController::loadData: invalid field description generated by the table row!");
886 0 : if ( pActFieldDescr )
887 : {
888 0 : pActFieldDescr->SetName(sName);
889 0 : pActFieldDescr->SetFormatKey(nFormatKey);
890 0 : pActFieldDescr->SetDescription(sDescription);
891 0 : pActFieldDescr->SetHelpText(sHelpText);
892 0 : pActFieldDescr->SetAutoIncrement(bIsAutoIncrement);
893 0 : pActFieldDescr->SetHorJustify(dbaui::mapTextJustify(nAlign));
894 0 : pActFieldDescr->SetCurrency(bIsCurrency);
895 :
896 : //////////////////////////////////////////////////////////////////////
897 : // Spezielle Daten
898 0 : pActFieldDescr->SetIsNullable(nNullable);
899 0 : pActFieldDescr->SetControlDefault(aControlDefault);
900 0 : pActFieldDescr->SetPrecision(nPrecision);
901 0 : pActFieldDescr->SetScale(nScale);
902 : }
903 0 : m_vRowList.push_back( pTabEdRow);
904 0 : }
905 : // fill the primary key information
906 0 : Reference<XNameAccess> xKeyColumns = getKeyColumns();
907 0 : if(xKeyColumns.is())
908 : {
909 0 : Sequence< ::rtl::OUString> aKeyColumns = xKeyColumns->getElementNames();
910 0 : const ::rtl::OUString* pKeyBegin = aKeyColumns.getConstArray();
911 0 : const ::rtl::OUString* pKeyEnd = pKeyBegin + aKeyColumns.getLength();
912 :
913 0 : for(;pKeyBegin != pKeyEnd;++pKeyBegin)
914 : {
915 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator rowIter = m_vRowList.begin();
916 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator rowEnd = m_vRowList.end();
917 0 : for(;rowIter != rowEnd;++rowIter)
918 : {
919 0 : if((*rowIter)->GetActFieldDescr()->GetName() == *pKeyBegin)
920 : {
921 0 : (*rowIter)->SetPrimaryKey(sal_True);
922 0 : break;
923 : }
924 : }
925 0 : }
926 0 : }
927 : }
928 :
929 : //////////////////////////////////////////////////////////////////////
930 : // Leere Zeilen fuellen
931 :
932 0 : OTypeInfoMap::iterator aTypeIter = m_aTypeInfo.find(DataType::VARCHAR);
933 0 : if(aTypeIter == m_aTypeInfo.end())
934 0 : aTypeIter = m_aTypeInfo.begin();
935 :
936 : OSL_ENSURE(aTypeIter != m_aTypeInfo.end(),"We have no type information!");
937 :
938 0 : bool bReadRow = !isAddAllowed();
939 0 : for(sal_Int32 i=m_vRowList.size(); i < NEWCOLS; i++ )
940 : {
941 0 : pTabEdRow.reset(new OTableRow());
942 0 : pTabEdRow->SetReadOnly(bReadRow);
943 0 : m_vRowList.push_back( pTabEdRow);
944 0 : }
945 0 : }
946 : // -----------------------------------------------------------------------------
947 0 : Reference<XNameAccess> OTableController::getKeyColumns() const
948 : {
949 0 : return getPrimaryKeyColumns_throw(m_xTable);
950 : }
951 : // -----------------------------------------------------------------------------
952 0 : sal_Bool OTableController::checkColumns(sal_Bool _bNew) throw(::com::sun::star::sdbc::SQLException)
953 : {
954 0 : sal_Bool bOk = sal_True;
955 0 : sal_Bool bFoundPKey = sal_False;
956 0 : Reference< XDatabaseMetaData > xMetaData = getMetaData( );
957 0 : DatabaseMetaData aMetaData( getConnection() );
958 :
959 0 : ::comphelper::UStringMixEqual bCase(xMetaData.is() ? xMetaData->supportsMixedCaseQuotedIdentifiers() : sal_True);
960 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin();
961 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end();
962 0 : for(;aIter != aEnd;++aIter)
963 : {
964 0 : OFieldDescription* pFieldDesc = (*aIter)->GetActFieldDescr();
965 0 : if (pFieldDesc && !pFieldDesc->GetName().isEmpty())
966 : {
967 0 : bFoundPKey |= (*aIter)->IsPrimaryKey();
968 : // first check for duplicate names
969 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter2 = aIter+1;
970 0 : for(;aIter2 != aEnd;++aIter2)
971 : {
972 0 : OFieldDescription* pCompareDesc = (*aIter2)->GetActFieldDescr();
973 0 : if (pCompareDesc && bCase(pCompareDesc->GetName(),pFieldDesc->GetName()))
974 : {
975 0 : String strMessage = String(ModuleRes(STR_TABLEDESIGN_DUPLICATE_NAME));
976 0 : strMessage.SearchAndReplaceAscii("$column$", pFieldDesc->GetName());
977 0 : OSQLWarningBox( getView(), strMessage ).Execute();
978 0 : return sal_False;
979 : }
980 : }
981 : }
982 : }
983 0 : if ( _bNew && !bFoundPKey && aMetaData.supportsPrimaryKeys() )
984 : {
985 0 : String sTitle(ModuleRes(STR_TABLEDESIGN_NO_PRIM_KEY_HEAD));
986 0 : String sMsg(ModuleRes(STR_TABLEDESIGN_NO_PRIM_KEY));
987 0 : OSQLMessageBox aBox(getView(), sTitle,sMsg, WB_YES_NO_CANCEL | WB_DEF_YES);
988 :
989 0 : switch ( aBox.Execute() )
990 : {
991 : case RET_YES:
992 : {
993 0 : ::boost::shared_ptr<OTableRow> pNewRow(new OTableRow());
994 0 : TOTypeInfoSP pTypeInfo = ::dbaui::queryPrimaryKeyType(m_aTypeInfo);
995 0 : if ( !pTypeInfo.get() )
996 : break;
997 :
998 0 : pNewRow->SetFieldType( pTypeInfo );
999 0 : OFieldDescription* pActFieldDescr = pNewRow->GetActFieldDescr();
1000 :
1001 0 : pActFieldDescr->SetAutoIncrement(sal_False);
1002 0 : pActFieldDescr->SetIsNullable(ColumnValue::NO_NULLS);
1003 :
1004 0 : pActFieldDescr->SetName( createUniqueName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ID")) ));
1005 0 : pActFieldDescr->SetPrimaryKey( sal_True );
1006 0 : m_vRowList.insert(m_vRowList.begin(),pNewRow);
1007 :
1008 0 : static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->Invalidate();
1009 0 : static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->RowInserted(0);
1010 : }
1011 0 : break;
1012 : case RET_CANCEL:
1013 0 : bOk = sal_False;
1014 0 : break;
1015 0 : }
1016 : }
1017 0 : return bOk;
1018 : }
1019 : // -----------------------------------------------------------------------------
1020 0 : void OTableController::alterColumns()
1021 : {
1022 0 : Reference<XColumnsSupplier> xColSup(m_xTable,UNO_QUERY_THROW);
1023 : OSL_ENSURE(xColSup.is(),"What happen here?!");
1024 :
1025 0 : Reference<XNameAccess> xColumns = xColSup->getColumns();
1026 0 : Reference<XIndexAccess> xIdxColumns(xColumns,UNO_QUERY_THROW);
1027 : OSL_ENSURE(xColumns.is(),"No columns");
1028 0 : if ( !xColumns.is() )
1029 0 : return;
1030 0 : Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY); // can be null
1031 :
1032 0 : sal_Int32 nColumnCount = xIdxColumns->getCount();
1033 0 : Reference<XDrop> xDrop(xColumns,UNO_QUERY); // can be null
1034 0 : Reference<XAppend> xAppend(xColumns,UNO_QUERY); // can be null
1035 0 : Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY); // can be null
1036 :
1037 0 : sal_Bool bReload = sal_False; // refresh the data
1038 :
1039 : // contains all columns names which are already handled those which are not in the list will be deleted
1040 0 : Reference< XDatabaseMetaData> xMetaData = getMetaData( );
1041 :
1042 0 : ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess> aColumns(xMetaData.is() ? (xMetaData->supportsMixedCaseQuotedIdentifiers() ? true : false): sal_True);
1043 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aIter = m_vRowList.begin();
1044 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aEnd = m_vRowList.end();
1045 : // first look for columns where something other than the name changed
1046 0 : sal_Int32 nPos = 0;
1047 0 : for(;aIter != aEnd;++aIter,++nPos)
1048 : {
1049 : OSL_ENSURE(*aIter,"OTableRow is null!");
1050 0 : OFieldDescription* pField = (*aIter)->GetActFieldDescr();
1051 0 : if ( !pField )
1052 0 : continue;
1053 0 : if ( (*aIter)->IsReadOnly() )
1054 : {
1055 0 : aColumns[pField->GetName()] = sal_True;
1056 0 : continue;
1057 : }
1058 :
1059 0 : Reference<XPropertySet> xColumn;
1060 0 : if ( xColumns->hasByName(pField->GetName()) )
1061 : {
1062 0 : aColumns[pField->GetName()] = sal_True;
1063 0 : xColumns->getByName(pField->GetName()) >>= xColumn;
1064 : OSL_ENSURE(xColumn.is(),"Column is null!");
1065 :
1066 0 : sal_Int32 nType=0,nPrecision=0,nScale=0,nNullable=0;
1067 0 : sal_Bool bAutoIncrement = false;
1068 0 : ::rtl::OUString sTypeName,sDescription;
1069 :
1070 0 : xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType;
1071 0 : xColumn->getPropertyValue(PROPERTY_PRECISION) >>= nPrecision;
1072 0 : xColumn->getPropertyValue(PROPERTY_SCALE) >>= nScale;
1073 0 : xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable;
1074 0 : xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT) >>= bAutoIncrement;
1075 0 : xColumn->getPropertyValue(PROPERTY_DESCRIPTION) >>= sDescription;
1076 :
1077 0 : try { xColumn->getPropertyValue(PROPERTY_TYPENAME) >>= sTypeName; }
1078 0 : catch( const Exception& )
1079 : {
1080 : OSL_FAIL( "no TypeName property?!" );
1081 : // since this is a last minute fix for #i41785#, I want to be on the safe side,
1082 : // and catch errors here as early as possible (instead of the whole process of altering
1083 : // the columns failing)
1084 : // Normally, sdbcx::Column objects are expected to have a TypeName property
1085 : }
1086 :
1087 : // check if something changed
1088 0 : if((nType != pField->GetType() ||
1089 0 : sTypeName != pField->GetTypeName() ||
1090 0 : (nPrecision != pField->GetPrecision() && nPrecision ) ||
1091 0 : nScale != pField->GetScale() ||
1092 0 : nNullable != pField->GetIsNullable() ||
1093 0 : sDescription != pField->GetDescription() ||
1094 0 : bAutoIncrement != pField->IsAutoIncrement())&&
1095 0 : xColumnFactory.is())
1096 : {
1097 0 : Reference<XPropertySet> xNewColumn;
1098 0 : xNewColumn = xColumnFactory->createDataDescriptor();
1099 0 : ::dbaui::setColumnProperties(xNewColumn,pField);
1100 : // first try to alter the column
1101 0 : sal_Bool bNotOk = sal_False;
1102 : try
1103 : {
1104 : // first try if we can alter the column
1105 0 : if(xAlter.is())
1106 0 : xAlter->alterColumnByName(pField->GetName(),xNewColumn);
1107 : }
1108 0 : catch(const SQLException&)
1109 : {
1110 0 : if(xDrop.is() && xAppend.is())
1111 : {
1112 0 : String aMessage( ModuleRes( STR_TABLEDESIGN_ALTER_ERROR ) );
1113 0 : aMessage.SearchAndReplaceAscii( "$column$", pField->GetName() );
1114 :
1115 0 : SQLExceptionInfo aError( ::cppu::getCaughtException() );
1116 0 : OSQLWarningBox aMsg( getView(), aMessage, WB_YES_NO | WB_DEF_YES , &aError );
1117 0 : bNotOk = aMsg.Execute() == RET_YES;
1118 : }
1119 : else
1120 0 : throw;
1121 : }
1122 : // if something went wrong or we can't alter columns
1123 : // drop and append a new one
1124 0 : if((!xAlter.is() || bNotOk) && xDrop.is() && xAppend.is())
1125 : {
1126 0 : xDrop->dropByName(pField->GetName());
1127 : try
1128 : {
1129 0 : xAppend->appendByDescriptor(xNewColumn);
1130 : }
1131 0 : catch(const SQLException&)
1132 : { // an error occurred so we try to reactivate the old one
1133 0 : xAppend->appendByDescriptor(xColumn);
1134 0 : throw;
1135 : }
1136 : }
1137 : // exceptions are caught outside
1138 0 : xNewColumn = NULL;
1139 0 : if(xColumns->hasByName(pField->GetName()))
1140 0 : xColumns->getByName(pField->GetName()) >>= xColumn;
1141 0 : bReload = sal_True;
1142 0 : }
1143 :
1144 :
1145 : }
1146 0 : else if(xColumnFactory.is() && xAlter.is() && nPos < nColumnCount)
1147 : { // we can't find the column so we could try it with the index before we drop and append a new column
1148 : try
1149 : {
1150 0 : Reference<XPropertySet> xNewColumn;
1151 0 : xNewColumn = xColumnFactory->createDataDescriptor();
1152 0 : ::dbaui::setColumnProperties(xNewColumn,pField);
1153 0 : xAlter->alterColumnByIndex(nPos,xNewColumn);
1154 0 : if(xColumns->hasByName(pField->GetName()))
1155 : { // ask for the append by name
1156 0 : aColumns[pField->GetName()] = sal_True;
1157 0 : xColumns->getByName(pField->GetName()) >>= xColumn;
1158 0 : if(xColumn.is())
1159 0 : pField->copyColumnSettingsTo(xColumn);
1160 : }
1161 : else
1162 : {
1163 : OSL_FAIL("OTableController::alterColumns: invalid column (2)!");
1164 0 : }
1165 : }
1166 0 : catch(const SQLException&)
1167 : { // we couldn't alter the column so we have to add new columns
1168 0 : bReload = sal_True;
1169 0 : if(xDrop.is() && xAppend.is())
1170 : {
1171 0 : String aMessage(ModuleRes(STR_TABLEDESIGN_ALTER_ERROR));
1172 0 : aMessage.SearchAndReplaceAscii("$column$",pField->GetName());
1173 0 : OSQLWarningBox aMsg( getView(), aMessage, WB_YES_NO | WB_DEF_YES );
1174 0 : if ( aMsg.Execute() != RET_YES )
1175 : {
1176 0 : Reference<XPropertySet> xNewColumn(xIdxColumns->getByIndex(nPos),UNO_QUERY_THROW);
1177 0 : ::rtl::OUString sName;
1178 0 : xNewColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
1179 0 : aColumns[sName] = sal_True;
1180 0 : aColumns[pField->GetName()] = sal_True;
1181 0 : continue;
1182 0 : }
1183 : }
1184 : else
1185 0 : throw;
1186 : }
1187 : }
1188 : else
1189 0 : bReload = sal_True;
1190 0 : }
1191 : // alter column settings
1192 0 : aIter = m_vRowList.begin();
1193 :
1194 : // first look for columns where something other than the name changed
1195 0 : for(nPos = 0;aIter != aEnd;++aIter,++nPos)
1196 : {
1197 : OSL_ENSURE(*aIter,"OTableRow is null!");
1198 0 : OFieldDescription* pField = (*aIter)->GetActFieldDescr();
1199 0 : if ( !pField )
1200 0 : continue;
1201 0 : if ( (*aIter)->IsReadOnly() )
1202 : {
1203 0 : aColumns[pField->GetName()] = sal_True;
1204 0 : continue;
1205 : }
1206 :
1207 0 : Reference<XPropertySet> xColumn;
1208 0 : if ( xColumns->hasByName(pField->GetName()) )
1209 : {
1210 0 : xColumns->getByName(pField->GetName()) >>= xColumn;
1211 0 : Reference<XPropertySetInfo> xInfo = xColumn->getPropertySetInfo();
1212 0 : if ( xInfo->hasPropertyByName(PROPERTY_HELPTEXT) )
1213 0 : xColumn->setPropertyValue(PROPERTY_HELPTEXT,makeAny(pField->GetHelpText()));
1214 :
1215 0 : if(xInfo->hasPropertyByName(PROPERTY_CONTROLDEFAULT))
1216 0 : xColumn->setPropertyValue(PROPERTY_CONTROLDEFAULT,pField->GetControlDefault());
1217 0 : if(xInfo->hasPropertyByName(PROPERTY_FORMATKEY))
1218 0 : xColumn->setPropertyValue(PROPERTY_FORMATKEY,makeAny(pField->GetFormatKey()));
1219 0 : if(xInfo->hasPropertyByName(PROPERTY_ALIGN))
1220 0 : xColumn->setPropertyValue(PROPERTY_ALIGN,makeAny(dbaui::mapTextAllign(pField->GetHorJustify())));
1221 : }
1222 0 : }
1223 : // second drop all columns which could be found by name
1224 0 : Reference<XNameAccess> xKeyColumns = getKeyColumns();
1225 : // now we have to look for the columns who could be deleted
1226 0 : if ( xDrop.is() )
1227 : {
1228 0 : Sequence< ::rtl::OUString> aColumnNames = xColumns->getElementNames();
1229 0 : const ::rtl::OUString* pIter = aColumnNames.getConstArray();
1230 0 : const ::rtl::OUString* pEnd = pIter + aColumnNames.getLength();
1231 0 : for(;pIter != pEnd;++pIter)
1232 : {
1233 0 : if(aColumns.find(*pIter) == aColumns.end()) // found a column to delete
1234 : {
1235 0 : if(xKeyColumns.is() && xKeyColumns->hasByName(*pIter)) // check if this column is a member of the primary key
1236 : {
1237 0 : String aMsgT(ModuleRes(STR_TBL_COLUMN_IS_KEYCOLUMN));
1238 0 : aMsgT.SearchAndReplaceAscii("$column$",*pIter);
1239 0 : String aTitle(ModuleRes(STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE));
1240 0 : OSQLMessageBox aMsg(getView(),aTitle,aMsgT,WB_YES_NO| WB_DEF_YES);
1241 0 : if(aMsg.Execute() == RET_YES)
1242 : {
1243 0 : xKeyColumns = NULL;
1244 0 : dropPrimaryKey();
1245 : }
1246 : else
1247 : {
1248 0 : bReload = sal_True;
1249 0 : continue;
1250 0 : }
1251 : }
1252 : try
1253 : {
1254 0 : xDrop->dropByName(*pIter);
1255 : }
1256 0 : catch (const SQLException&)
1257 : {
1258 0 : String sError( ModuleRes( STR_TABLEDESIGN_COULD_NOT_DROP_COL ) );
1259 0 : sError.SearchAndReplaceAscii( "$column$", *pIter );
1260 :
1261 0 : SQLException aNewException;
1262 0 : aNewException.Message = sError;
1263 0 : aNewException.SQLState = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000"));
1264 0 : aNewException.NextException = ::cppu::getCaughtException();
1265 :
1266 0 : throw aNewException;
1267 : }
1268 : }
1269 0 : }
1270 : }
1271 :
1272 : // third append the new columns
1273 0 : aIter = m_vRowList.begin();
1274 0 : for(;aIter != aEnd;++aIter)
1275 : {
1276 : OSL_ENSURE(*aIter,"OTableRow is null!");
1277 0 : OFieldDescription* pField = (*aIter)->GetActFieldDescr();
1278 0 : if ( !pField || (*aIter)->IsReadOnly() || aColumns.find(pField->GetName()) != aColumns.end() )
1279 0 : continue;
1280 :
1281 0 : Reference<XPropertySet> xColumn;
1282 0 : if(!xColumns->hasByName(pField->GetName()))
1283 : {
1284 0 : if(xColumnFactory.is() && xAppend.is())
1285 : {// column not found by its name so we assume it is new
1286 : // Column is new
1287 0 : xColumn = xColumnFactory->createDataDescriptor();
1288 0 : ::dbaui::setColumnProperties(xColumn,pField);
1289 0 : xAppend->appendByDescriptor(xColumn);
1290 0 : if(xColumns->hasByName(pField->GetName()))
1291 : { // ask for the append by name
1292 0 : aColumns[pField->GetName()] = sal_True;
1293 0 : xColumns->getByName(pField->GetName()) >>= xColumn;
1294 0 : if(xColumn.is())
1295 0 : pField->copyColumnSettingsTo(xColumn);
1296 : }
1297 : else
1298 : {
1299 : OSL_FAIL("OTableController::alterColumns: invalid column!");
1300 : }
1301 : }
1302 : }
1303 0 : }
1304 :
1305 :
1306 : // check if we have to do something with the primary key
1307 0 : sal_Bool bNeedDropKey = sal_False;
1308 0 : sal_Bool bNeedAppendKey = sal_False;
1309 0 : if ( xKeyColumns.is() )
1310 : {
1311 0 : aIter = m_vRowList.begin();
1312 0 : for(;aIter != aEnd;++aIter)
1313 : {
1314 : OSL_ENSURE(*aIter,"OTableRow is null!");
1315 0 : OFieldDescription* pField = (*aIter)->GetActFieldDescr();
1316 0 : if ( !pField )
1317 0 : continue;
1318 :
1319 0 : if ( pField->IsPrimaryKey()
1320 0 : && !xKeyColumns->hasByName( pField->GetName() )
1321 : )
1322 : { // new primary key column inserted which isn't already in the columns selection
1323 0 : bNeedDropKey = bNeedAppendKey = sal_True;
1324 0 : break;
1325 : }
1326 0 : else if ( !pField->IsPrimaryKey()
1327 0 : && xKeyColumns->hasByName( pField->GetName() )
1328 : )
1329 : { // found a column which currently is in the primary key, but is marked not to be anymore
1330 0 : bNeedDropKey = bNeedAppendKey = sal_True;
1331 0 : break;
1332 : }
1333 : }
1334 : }
1335 : else
1336 : { // no primary key available so we check if we should create one
1337 0 : bNeedAppendKey = sal_True;
1338 : }
1339 :
1340 0 : if ( bNeedDropKey && xKeyColumns.is() && xKeyColumns->getElementNames().getLength() )
1341 0 : dropPrimaryKey();
1342 :
1343 0 : if ( bNeedAppendKey )
1344 : {
1345 0 : Reference< XKeysSupplier > xKeySup( m_xTable, UNO_QUERY );
1346 0 : appendPrimaryKey( xKeySup ,sal_False);
1347 : }
1348 :
1349 0 : reSyncRows();
1350 :
1351 0 : if ( bReload )
1352 0 : reload();
1353 : }
1354 : // -----------------------------------------------------------------------------
1355 0 : void OTableController::dropPrimaryKey()
1356 : {
1357 0 : SQLExceptionInfo aInfo;
1358 : try
1359 : {
1360 0 : Reference<XKeysSupplier> xKeySup(m_xTable,UNO_QUERY);
1361 0 : Reference<XIndexAccess> xKeys;
1362 0 : if(xKeySup.is())
1363 0 : xKeys = xKeySup->getKeys();
1364 :
1365 0 : if(xKeys.is())
1366 : {
1367 0 : Reference<XPropertySet> xProp;
1368 0 : for(sal_Int32 i=0;i< xKeys->getCount();++i)
1369 : {
1370 0 : xProp.set(xKeys->getByIndex(i),UNO_QUERY);
1371 0 : sal_Int32 nKeyType = 0;
1372 0 : xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
1373 0 : if(KeyType::PRIMARY == nKeyType)
1374 : {
1375 0 : Reference<XDrop> xDrop(xKeys,UNO_QUERY);
1376 0 : xDrop->dropByIndex(i); // delete the key
1377 0 : break;
1378 : }
1379 0 : }
1380 0 : }
1381 : }
1382 0 : catch(const SQLContext& e)
1383 : {
1384 0 : aInfo = SQLExceptionInfo(e);
1385 : }
1386 0 : catch(const SQLWarning& e)
1387 : {
1388 0 : aInfo = SQLExceptionInfo(e);
1389 : }
1390 0 : catch(const SQLException& e)
1391 : {
1392 0 : aInfo = SQLExceptionInfo(e);
1393 : }
1394 0 : catch( const Exception& )
1395 : {
1396 : DBG_UNHANDLED_EXCEPTION();
1397 : }
1398 :
1399 0 : showError(aInfo);
1400 0 : }
1401 : // -----------------------------------------------------------------------------
1402 0 : void OTableController::assignTable()
1403 : {
1404 : // get the table
1405 0 : if(!m_sName.isEmpty())
1406 : {
1407 0 : Reference<XNameAccess> xNameAccess;
1408 0 : Reference<XTablesSupplier> xSup(getConnection(),UNO_QUERY);
1409 0 : if(xSup.is())
1410 : {
1411 0 : xNameAccess = xSup->getTables();
1412 : OSL_ENSURE(xNameAccess.is(),"no nameaccess for the queries!");
1413 :
1414 0 : Reference<XPropertySet> xProp;
1415 0 : if(xNameAccess->hasByName(m_sName) && ::cppu::extractInterface(xProp,xNameAccess->getByName(m_sName)) && xProp.is())
1416 : {
1417 0 : m_xTable = xProp;
1418 0 : startTableListening();
1419 :
1420 : // check if we set the table editable
1421 0 : Reference<XDatabaseMetaData> xMeta = getConnection()->getMetaData();
1422 0 : setEditable( xMeta.is() && !xMeta->isReadOnly() && (isAlterAllowed() || isDropAllowed() || isAddAllowed()) );
1423 0 : if(!isEditable())
1424 : {
1425 0 : ::std::for_each(m_vRowList.begin(),m_vRowList.end(),boost::bind( &OTableRow::SetReadOnly, _1, boost::cref( sal_True )));
1426 : }
1427 0 : m_bNew = sal_False;
1428 : // be notified when the table is in disposing
1429 0 : InvalidateAll();
1430 0 : }
1431 0 : }
1432 : }
1433 0 : }
1434 : // -----------------------------------------------------------------------------
1435 0 : sal_Bool OTableController::isAddAllowed() const
1436 : {
1437 0 : Reference<XColumnsSupplier> xColsSup(m_xTable,UNO_QUERY);
1438 0 : sal_Bool bAddAllowed = !m_xTable.is();
1439 0 : if(xColsSup.is())
1440 0 : bAddAllowed = Reference<XAppend>(xColsSup->getColumns(),UNO_QUERY).is();
1441 :
1442 : try
1443 : {
1444 0 : Reference< XDatabaseMetaData > xMetaData = getMetaData( );
1445 0 : bAddAllowed = bAddAllowed || ( xMetaData.is() && xMetaData->supportsAlterTableWithAddColumn());
1446 : }
1447 0 : catch(Exception&)
1448 : {
1449 : DBG_UNHANDLED_EXCEPTION();
1450 0 : bAddAllowed = sal_False;
1451 : }
1452 :
1453 0 : return bAddAllowed;
1454 : }
1455 : // -----------------------------------------------------------------------------
1456 0 : sal_Bool OTableController::isDropAllowed() const
1457 : {
1458 0 : Reference<XColumnsSupplier> xColsSup(m_xTable,UNO_QUERY);
1459 0 : sal_Bool bDropAllowed = !m_xTable.is();
1460 0 : if(xColsSup.is())
1461 : {
1462 0 : Reference<XNameAccess> xNameAccess = xColsSup->getColumns();
1463 0 : bDropAllowed = Reference<XDrop>(xNameAccess,UNO_QUERY).is() && xNameAccess->hasElements();
1464 : }
1465 :
1466 0 : Reference< XDatabaseMetaData> xMetaData = getMetaData( );
1467 0 : bDropAllowed = bDropAllowed || ( xMetaData.is() && xMetaData->supportsAlterTableWithDropColumn());
1468 :
1469 0 : return bDropAllowed;
1470 : }
1471 : // -----------------------------------------------------------------------------
1472 0 : sal_Bool OTableController::isAlterAllowed() const
1473 : {
1474 0 : sal_Bool bAllowed(!m_xTable.is() || Reference<XAlterTable>(m_xTable,UNO_QUERY).is());
1475 0 : return bAllowed;
1476 : }
1477 : // -----------------------------------------------------------------------------
1478 0 : void OTableController::reSyncRows()
1479 : {
1480 0 : sal_Bool bAlterAllowed = isAlterAllowed();
1481 0 : sal_Bool bAddAllowed = isAddAllowed();
1482 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aIter = m_vRowList.begin();
1483 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aEnd = m_vRowList.end();
1484 0 : for(;aIter != aEnd;++aIter)
1485 : {
1486 : OSL_ENSURE(*aIter,"OTableRow is null!");
1487 0 : OFieldDescription* pField = (*aIter)->GetActFieldDescr();
1488 0 : if ( pField )
1489 0 : (*aIter)->SetReadOnly(!bAlterAllowed);
1490 : else
1491 0 : (*aIter)->SetReadOnly(!bAddAllowed);
1492 :
1493 : }
1494 0 : static_cast<OTableDesignView*>(getView())->reSync(); // show the windows and fill with our informations
1495 :
1496 0 : ClearUndoManager();
1497 0 : setModified(sal_False); // and we are not modified yet
1498 0 : }
1499 : // -----------------------------------------------------------------------------
1500 0 : ::rtl::OUString OTableController::createUniqueName(const ::rtl::OUString& _rName)
1501 : {
1502 0 : ::rtl::OUString sName = _rName;
1503 0 : Reference< XDatabaseMetaData> xMetaData = getMetaData( );
1504 :
1505 0 : ::comphelper::UStringMixEqual bCase(xMetaData.is() ? xMetaData->supportsMixedCaseQuotedIdentifiers() : sal_True);
1506 :
1507 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin();
1508 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end();
1509 0 : for(sal_Int32 i=0;aIter != aEnd;++aIter)
1510 : {
1511 0 : OFieldDescription* pFieldDesc = (*aIter)->GetActFieldDescr();
1512 0 : if (pFieldDesc && !pFieldDesc->GetName().isEmpty() && bCase(sName,pFieldDesc->GetName()))
1513 : { // found a second name of _rName so we need another
1514 0 : sName = _rName + ::rtl::OUString::valueOf(++i);
1515 0 : aIter = m_vRowList.begin(); // and retry
1516 : }
1517 : }
1518 0 : return sName;
1519 : }
1520 : // -----------------------------------------------------------------------------
1521 0 : ::rtl::OUString OTableController::getPrivateTitle() const
1522 : {
1523 0 : ::rtl::OUString sTitle;
1524 : try
1525 : {
1526 : // get the table
1527 0 : if ( !m_sName.isEmpty() && getConnection().is() )
1528 : {
1529 0 : if ( m_xTable.is() )
1530 0 : sTitle = ::dbtools::composeTableName( getConnection()->getMetaData(), m_xTable, ::dbtools::eInDataManipulation, false, false, false );
1531 : else
1532 0 : sTitle = m_sName;
1533 : }
1534 0 : if ( sTitle.isEmpty() )
1535 : {
1536 0 : String aName = String(ModuleRes(STR_TBL_TITLE));
1537 0 : sTitle = aName.GetToken(0,' ');
1538 0 : sTitle += ::rtl::OUString::valueOf(getCurrentStartNumber());
1539 : }
1540 : }
1541 0 : catch( const Exception& )
1542 : {
1543 : DBG_UNHANDLED_EXCEPTION();
1544 : }
1545 0 : return sTitle;
1546 : }
1547 : // -----------------------------------------------------------------------------
1548 0 : void OTableController::reload()
1549 : {
1550 0 : loadData(); // fill the column information form the table
1551 0 : static_cast<OTableDesignView*>(getView())->reSync(); // show the windows and fill with our informations
1552 0 : ClearUndoManager();
1553 0 : setModified(sal_False); // and we are not modified yet
1554 0 : static_cast<OTableDesignView*>(getView())->Invalidate();
1555 0 : }
1556 : // -----------------------------------------------------------------------------
1557 0 : sal_Int32 OTableController::getFirstEmptyRowPosition()
1558 : {
1559 0 : sal_Int32 nRet = -1;
1560 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin();
1561 0 : ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end();
1562 0 : for(;aIter != aEnd;++aIter)
1563 : {
1564 0 : if ( !*aIter || !(*aIter)->GetActFieldDescr() || (*aIter)->GetActFieldDescr()->GetName().isEmpty() )
1565 : {
1566 0 : nRet = aIter - m_vRowList.begin();
1567 0 : break;
1568 : }
1569 : }
1570 0 : if ( nRet == -1 )
1571 : {
1572 0 : bool bReadRow = !isAddAllowed();
1573 0 : ::boost::shared_ptr<OTableRow> pTabEdRow(new OTableRow());
1574 0 : pTabEdRow->SetReadOnly(bReadRow);
1575 0 : nRet = m_vRowList.size();
1576 0 : m_vRowList.push_back( pTabEdRow);
1577 : }
1578 0 : return nRet;
1579 : }
1580 : // -----------------------------------------------------------------------------
1581 0 : bool OTableController::isAutoIncrementPrimaryKey() const
1582 : {
1583 0 : return getSdbMetaData().isAutoIncrementPrimaryKey();
1584 0 : }
1585 : // -----------------------------------------------------------------------------
1586 :
1587 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|