File: | home/maarten/src/libreoffice/core/include/rtl/ref.hxx |
Warning: | line 113, column 13 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <FieldDescriptions.hxx> | |||
21 | #include "TEditControl.hxx" | |||
22 | #include <TableController.hxx> | |||
23 | #include <TableDesignView.hxx> | |||
24 | #include <TableRow.hxx> | |||
25 | #include <TypeInfo.hxx> | |||
26 | #include <UITools.hxx> | |||
27 | #include <browserids.hxx> | |||
28 | #include <core_resource.hxx> | |||
29 | #include <strings.hrc> | |||
30 | #include <strings.hxx> | |||
31 | #include <defaultobjectnamecheck.hxx> | |||
32 | #include <dlgsave.hxx> | |||
33 | #include <indexdialog.hxx> | |||
34 | #include <sqlmessage.hxx> | |||
35 | ||||
36 | #include <com/sun/star/frame/XTitleChangeListener.hpp> | |||
37 | #include <com/sun/star/sdb/CommandType.hpp> | |||
38 | #include <com/sun/star/sdb/SQLContext.hpp> | |||
39 | #include <com/sun/star/sdbc/ColumnValue.hpp> | |||
40 | #include <com/sun/star/sdbc/SQLWarning.hpp> | |||
41 | #include <com/sun/star/sdbcx/KeyType.hpp> | |||
42 | #include <com/sun/star/sdbcx/XAlterTable.hpp> | |||
43 | #include <com/sun/star/sdbcx/XAppend.hpp> | |||
44 | #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> | |||
45 | #include <com/sun/star/sdbcx/XDrop.hpp> | |||
46 | #include <com/sun/star/sdbcx/XIndexesSupplier.hpp> | |||
47 | #include <com/sun/star/sdbcx/XTablesSupplier.hpp> | |||
48 | ||||
49 | #include <comphelper/processfactory.hxx> | |||
50 | #include <connectivity/dbexception.hxx> | |||
51 | #include <connectivity/dbtools.hxx> | |||
52 | #include <connectivity/dbmetadata.hxx> | |||
53 | #include <cppuhelper/exc_hlp.hxx> | |||
54 | #include <tools/diagnose_ex.h> | |||
55 | #include <vcl/svapp.hxx> | |||
56 | #include <vcl/weld.hxx> | |||
57 | ||||
58 | #include <algorithm> | |||
59 | #include <functional> | |||
60 | ||||
61 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface* | |||
62 | org_openoffice_comp_dbu_OTableDesign_get_implementation( | |||
63 | css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& ) | |||
64 | { | |||
65 | return cppu::acquire(new ::dbaui::OTableController(context)); | |||
66 | } | |||
67 | ||||
68 | using namespace ::com::sun::star; | |||
69 | using namespace ::com::sun::star::uno; | |||
70 | using namespace ::com::sun::star::io; | |||
71 | using namespace ::com::sun::star::beans; | |||
72 | using namespace ::com::sun::star::frame; | |||
73 | using namespace ::com::sun::star::lang; | |||
74 | using namespace ::com::sun::star::container; | |||
75 | using namespace ::com::sun::star::sdbcx; | |||
76 | using namespace ::com::sun::star::sdbc; | |||
77 | using namespace ::com::sun::star::sdb; | |||
78 | using namespace ::com::sun::star::ui; | |||
79 | using namespace ::com::sun::star::util; | |||
80 | using namespace ::dbtools; | |||
81 | using namespace ::dbaui; | |||
82 | using namespace ::comphelper; | |||
83 | ||||
84 | // number of columns when creating it from scratch | |||
85 | #define NEWCOLS128 128 | |||
86 | ||||
87 | namespace | |||
88 | { | |||
89 | void dropTable(const Reference<XNameAccess>& _rxTable,const OUString& _sTableName) | |||
90 | { | |||
91 | if ( _rxTable->hasByName(_sTableName) ) | |||
92 | { | |||
93 | Reference<XDrop> xNameCont(_rxTable,UNO_QUERY); | |||
94 | OSL_ENSURE(xNameCont.is(),"No drop interface for tables!")do { if (true && (!(xNameCont.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "94" ": "), "%s", "No drop interface for tables!"); } } while (false); | |||
95 | if ( xNameCont.is() ) | |||
96 | xNameCont->dropByName(_sTableName); | |||
97 | } | |||
98 | } | |||
99 | } | |||
100 | ||||
101 | OUString SAL_CALL OTableController::getImplementationName() | |||
102 | { | |||
103 | return "org.openoffice.comp.dbu.OTableDesign"; | |||
104 | } | |||
105 | ||||
106 | Sequence< OUString> OTableController::getSupportedServiceNames() | |||
107 | { | |||
108 | return { "com.sun.star.sdb.TableDesign" }; | |||
109 | } | |||
110 | ||||
111 | OTableController::OTableController(const Reference< XComponentContext >& _rM) : OTableController_BASE(_rM) | |||
112 | ,m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_DBFIELDTYPES" "\004" u8"Unknown;Text;Number;Date/Time;Date;Time;Yes/No;Currency;Memo;Counter;Image;Text (fix);Decimal;Binary (fix);Binary;BigInt;Double;Float;Real;Integer;Small Integer;Tiny Integer;SQL Null;Object;Distinct;Structure;Field;BLOB;CLOB;REF;OTHER;Bit (fix)" ) )) | |||
113 | ,m_pTypeInfo() | |||
114 | ,m_bAllowAutoIncrementValue(false) | |||
115 | ,m_bNew(true) | |||
116 | { | |||
117 | ||||
118 | InvalidateAll(); | |||
119 | m_pTypeInfo = std::make_shared<OTypeInfo>(); | |||
120 | m_pTypeInfo->aUIName = m_sTypeNames.getToken(TYPE_OTHER, ';'); | |||
121 | } | |||
122 | ||||
123 | OTableController::~OTableController() | |||
124 | { | |||
125 | m_aTypeInfoIndex.clear(); | |||
126 | m_aTypeInfo.clear(); | |||
127 | ||||
128 | } | |||
129 | ||||
130 | void OTableController::startTableListening() | |||
131 | { | |||
132 | Reference< XComponent > xComponent(m_xTable, UNO_QUERY); | |||
133 | if (xComponent.is()) | |||
134 | xComponent->addEventListener(static_cast<XModifyListener*>(this)); | |||
135 | } | |||
136 | ||||
137 | void OTableController::stopTableListening() | |||
138 | { | |||
139 | Reference< XComponent > xComponent(m_xTable, UNO_QUERY); | |||
140 | if (xComponent.is()) | |||
141 | xComponent->removeEventListener(static_cast<XModifyListener*>(this)); | |||
142 | } | |||
143 | ||||
144 | void OTableController::disposing() | |||
145 | { | |||
146 | OTableController_BASE::disposing(); | |||
147 | clearView(); | |||
148 | ||||
149 | m_vRowList.clear(); | |||
150 | } | |||
151 | ||||
152 | FeatureState OTableController::GetState(sal_uInt16 _nId) const | |||
153 | { | |||
154 | FeatureState aReturn; | |||
155 | // disabled automatically | |||
156 | ||||
157 | switch (_nId) | |||
158 | { | |||
159 | case ID_BROWSER_CLOSE(5000 + 621): | |||
160 | aReturn.bEnabled = true; | |||
161 | break; | |||
162 | case ID_BROWSER_EDITDOC(5000 + 1312): | |||
163 | aReturn.bChecked = isEditable(); | |||
164 | aReturn.bEnabled = true; | |||
165 | break; | |||
166 | case ID_BROWSER_SAVEDOC(5000 + 505): | |||
167 | aReturn.bEnabled = isEditable() && std::any_of(m_vRowList.begin(),m_vRowList.end(),std::mem_fn(&OTableRow::isValid)); | |||
168 | break; | |||
169 | case ID_BROWSER_SAVEASDOC(5000 + 502): | |||
170 | aReturn.bEnabled = isConnected() && isEditable(); | |||
171 | if ( aReturn.bEnabled ) | |||
172 | { | |||
173 | aReturn.bEnabled = std::any_of(m_vRowList.begin(),m_vRowList.end(), | |||
174 | std::mem_fn(&OTableRow::isValid)); | |||
175 | } | |||
176 | break; | |||
177 | ||||
178 | case ID_BROWSER_CUT(5000 + 710): | |||
179 | aReturn.bEnabled = isEditable() && getView() && static_cast<OTableDesignView*>(getView())->isCutAllowed(); | |||
180 | break; | |||
181 | case ID_BROWSER_COPY(5000 + 711): | |||
182 | aReturn.bEnabled = getView() && static_cast<OTableDesignView*>(getView())->isCopyAllowed(); | |||
183 | break; | |||
184 | case ID_BROWSER_PASTE(5000 + 712): | |||
185 | aReturn.bEnabled = isEditable() && getView() && static_cast<OTableDesignView*>(getView())->isPasteAllowed(); | |||
186 | break; | |||
187 | case SID_INDEXDESIGN( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 0 ): | |||
188 | aReturn.bEnabled = | |||
189 | ( ( ((!m_bNew && impl_isModified()) || impl_isModified()) | |||
190 | || Reference< XIndexesSupplier >(m_xTable, UNO_QUERY).is() | |||
191 | ) | |||
192 | && isConnected() | |||
193 | ); | |||
194 | if ( aReturn.bEnabled ) | |||
195 | { | |||
196 | aReturn.bEnabled = std::any_of(m_vRowList.begin(),m_vRowList.end(), | |||
197 | std::mem_fn(&OTableRow::isValid)); | |||
198 | } | |||
199 | break; | |||
200 | default: | |||
201 | aReturn = OTableController_BASE::GetState(_nId); | |||
202 | } | |||
203 | return aReturn; | |||
204 | } | |||
205 | ||||
206 | void OTableController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs) | |||
207 | { | |||
208 | switch(_nId) | |||
209 | { | |||
210 | case ID_BROWSER_EDITDOC(5000 + 1312): | |||
211 | setEditable(!isEditable()); | |||
212 | static_cast<OTableDesignView*>(getView())->setReadOnly(!isEditable()); | |||
213 | InvalidateFeature(ID_BROWSER_SAVEDOC(5000 + 505)); | |||
214 | InvalidateFeature(ID_BROWSER_PASTE(5000 + 712)); | |||
215 | InvalidateFeature(SID_BROWSER_CLEAR_QUERY( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 44 )); | |||
216 | break; | |||
217 | case ID_BROWSER_SAVEASDOC(5000 + 502): | |||
218 | doSaveDoc(true); | |||
219 | break; | |||
220 | case ID_BROWSER_SAVEDOC(5000 + 505): | |||
221 | static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->SaveCurRow(); | |||
222 | doSaveDoc(false); | |||
223 | break; | |||
224 | case ID_BROWSER_CUT(5000 + 710): | |||
225 | static_cast<OTableDesignView*>(getView())->cut(); | |||
226 | break; | |||
227 | case ID_BROWSER_COPY(5000 + 711): | |||
228 | static_cast<OTableDesignView*>(getView())->copy(); | |||
229 | break; | |||
230 | case ID_BROWSER_PASTE(5000 + 712): | |||
231 | static_cast<OTableDesignView*>(getView())->paste(); | |||
232 | break; | |||
233 | case SID_INDEXDESIGN( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 0 ): | |||
234 | doEditIndexes(); | |||
235 | break; | |||
236 | default: | |||
237 | OTableController_BASE::Execute(_nId,aArgs); | |||
238 | } | |||
239 | InvalidateFeature(_nId); | |||
240 | } | |||
241 | ||||
242 | bool OTableController::doSaveDoc(bool _bSaveAs) | |||
243 | { | |||
244 | if (!isConnected()) | |||
245 | reconnect(true); // ask the user for a new connection | |||
246 | Reference<XTablesSupplier> xTablesSup(getConnection(),UNO_QUERY); | |||
247 | ||||
248 | if (!xTablesSup.is()) | |||
249 | { | |||
250 | OUString aMessage(DBA_RES(STR_TABLEDESIGN_CONNECTION_MISSING)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_CONNECTION_MISSING" "\004" u8"The table could not be saved due to problems connecting to the database." ) )); | |||
251 | OSQLWarningBox aWarning(getFrameWeld(), aMessage); | |||
252 | aWarning.run(); | |||
253 | return false; | |||
254 | } | |||
255 | ||||
256 | // check if a column exists | |||
257 | // TODO | |||
258 | ||||
259 | Reference<XNameAccess> xTables; | |||
260 | OUString sCatalog, sSchema; | |||
261 | ||||
262 | bool bNew = m_sName.isEmpty(); | |||
263 | bNew = bNew || m_bNew || _bSaveAs; | |||
264 | ||||
265 | try | |||
266 | { | |||
267 | xTables = xTablesSup->getTables(); | |||
268 | OSL_ENSURE(xTables.is(),"The tables can't be null!")do { if (true && (!(xTables.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "268" ": "), "%s", "The tables can't be null!"); } } while (false); | |||
269 | bNew = bNew || (xTables.is() && !xTables->hasByName(m_sName)); | |||
270 | ||||
271 | // first we need a name for our query so ask the user | |||
272 | if(bNew) | |||
273 | { | |||
274 | OUString aName = DBA_RES(STR_TBL_TITLE)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TBL_TITLE" "\004" u8"Table #") ); | |||
275 | OUString aDefaultName = aName.getToken(0,' '); | |||
276 | aDefaultName = ::dbtools::createUniqueName(xTables,aDefaultName); | |||
277 | ||||
278 | DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::TABLE ); | |||
279 | OSaveAsDlg aDlg(getFrameWeld(), CommandType::TABLE, getORB(), getConnection(), aDefaultName, aNameChecker, SADFlags::NONE); | |||
280 | if (aDlg.run() != RET_OK) | |||
281 | return false; | |||
282 | ||||
283 | m_sName = aDlg.getName(); | |||
284 | sCatalog = aDlg.getCatalog(); | |||
285 | sSchema = aDlg.getSchema(); | |||
286 | } | |||
287 | ||||
288 | // did we get a name | |||
289 | if(m_sName.isEmpty()) | |||
290 | return false; | |||
291 | } | |||
292 | catch(Exception&) | |||
293 | { | |||
294 | OSL_FAIL("OTableController::doSaveDoc: nothing is expected to happen here!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "294" ": "), "%s", "OTableController::doSaveDoc: nothing is expected to happen here!" ); } } while (false); | |||
295 | } | |||
296 | ||||
297 | bool bAlter = false; | |||
298 | bool bError = false; | |||
299 | SQLExceptionInfo aInfo; | |||
300 | try | |||
301 | { | |||
302 | // check the columns for double names | |||
303 | if(!checkColumns(bNew || !xTables->hasByName(m_sName))) | |||
304 | { | |||
305 | return false; | |||
306 | } | |||
307 | ||||
308 | Reference<XPropertySet> xTable; | |||
309 | if(bNew || !xTables->hasByName(m_sName)) // just to make sure the table already exists | |||
310 | { | |||
311 | dropTable(xTables,m_sName); | |||
312 | ||||
313 | Reference<XDataDescriptorFactory> xFact(xTables,UNO_QUERY); | |||
314 | OSL_ENSURE(xFact.is(),"OTableController::doSaveDoc: No XDataDescriptorFactory available!")do { if (true && (!(xFact.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "314" ": "), "%s", "OTableController::doSaveDoc: No XDataDescriptorFactory available!" ); } } while (false); | |||
315 | xTable = xFact->createDataDescriptor(); | |||
316 | OSL_ENSURE(xTable.is(),"OTableController::doSaveDoc: Create query failed!")do { if (true && (!(xTable.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "316" ": "), "%s", "OTableController::doSaveDoc: Create query failed!" ); } } while (false); | |||
317 | // to set the name is only allowed when the query is new | |||
318 | xTable->setPropertyValue(PROPERTY_CATALOGNAME"CatalogName",makeAny(sCatalog)); | |||
319 | xTable->setPropertyValue(PROPERTY_SCHEMANAME"SchemaName",makeAny(sSchema)); | |||
320 | xTable->setPropertyValue(PROPERTY_NAME"Name",makeAny(m_sName)); | |||
321 | ||||
322 | // now append the columns | |||
323 | Reference<XColumnsSupplier> xColSup(xTable,UNO_QUERY); | |||
324 | appendColumns(xColSup,bNew); | |||
325 | // now append the primary key | |||
326 | Reference<XKeysSupplier> xKeySup(xTable,UNO_QUERY); | |||
327 | appendPrimaryKey(xKeySup,bNew); | |||
328 | } | |||
329 | // now set the properties | |||
330 | if(bNew) | |||
331 | { | |||
332 | Reference<XAppend> xAppend(xTables,UNO_QUERY); | |||
333 | OSL_ENSURE(xAppend.is(),"OTableController::doSaveDoc: No XAppend Interface!")do { if (true && (!(xAppend.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "333" ": "), "%s", "OTableController::doSaveDoc: No XAppend Interface!" ); } } while (false); | |||
334 | xAppend->appendByDescriptor(xTable); | |||
335 | ||||
336 | assignTable(); | |||
337 | if(!m_xTable.is()) // correct name and try again | |||
338 | { | |||
339 | // it can be that someone inserted new data for us | |||
340 | m_sName = ::dbtools::composeTableName( getConnection()->getMetaData(), xTable, ::dbtools::EComposeRule::InDataManipulation, false ); | |||
341 | assignTable(); | |||
342 | } | |||
343 | // now check if our datasource has set a tablefilter and if append the new table name to it | |||
344 | ::dbaui::appendToFilter(getConnection(), m_sName, getORB(), getFrameWeld()); // we are not interested in the return value | |||
345 | Reference< frame::XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY); | |||
346 | if ( xEventListener.is() ) | |||
347 | { | |||
348 | frame::TitleChangedEvent aEvent; | |||
349 | xEventListener->titleChanged(aEvent); | |||
350 | } | |||
351 | releaseNumberForComponent(); | |||
352 | } | |||
353 | else if(m_xTable.is()) | |||
354 | { | |||
355 | bAlter = true; | |||
356 | alterColumns(); | |||
357 | } | |||
358 | reSyncRows(); | |||
359 | } | |||
360 | catch(const SQLContext& e) | |||
361 | { | |||
362 | aInfo = SQLExceptionInfo(e); | |||
363 | } | |||
364 | catch(const SQLWarning& e) | |||
365 | { | |||
366 | aInfo = SQLExceptionInfo(e); | |||
367 | } | |||
368 | catch(const SQLException& e) | |||
369 | { | |||
370 | aInfo = SQLExceptionInfo(e); | |||
371 | } | |||
372 | catch(const ElementExistException& ) | |||
373 | { | |||
374 | OUString sText( DBA_RES( STR_NAME_ALREADY_EXISTS )::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_NAME_ALREADY_EXISTS" "\004" u8"The name \"#\" already exists." ) ) ); | |||
375 | sText = sText.replaceFirst( "#" , m_sName); | |||
376 | OSQLMessageBox aDlg(getFrameWeld(), DBA_RES( STR_ERROR_DURING_CREATION )::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_ERROR_DURING_CREATION" "\004" u8"Error during creation" ) ), sText, MessBoxStyle::Ok, MessageType::Error); | |||
377 | aDlg.run(); | |||
378 | bError = true; | |||
379 | } | |||
380 | catch( const Exception& ) | |||
381 | { | |||
382 | DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "382" ": ", "dbaccess" );; | |||
383 | bError = true; | |||
384 | } | |||
385 | ||||
386 | if ( aInfo.isValid() ) | |||
387 | aInfo.prepend( DBA_RES( STR_TABLEDESIGN_SAVE_ERROR )::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_SAVE_ERROR" "\004" u8"Error while saving the table design" ) ) ); | |||
388 | showError(aInfo); | |||
389 | ||||
390 | if (aInfo.isValid() || bError) | |||
391 | { | |||
392 | if(!bAlter || bNew) | |||
393 | { | |||
394 | m_sName.clear(); | |||
395 | stopTableListening(); | |||
396 | m_xTable = nullptr; | |||
397 | } | |||
398 | } | |||
399 | return ! (aInfo.isValid() || bError); | |||
400 | } | |||
401 | ||||
402 | void OTableController::doEditIndexes() | |||
403 | { | |||
404 | // table needs to be saved before editing indexes | |||
405 | if (m_bNew || isModified()) | |||
406 | { | |||
407 | std::unique_ptr<weld::MessageDialog> xAsk(Application::CreateMessageDialog(getFrameWeld(), | |||
408 | VclMessageType::Question, VclButtonsType::YesNo, | |||
409 | DBA_RES(STR_QUERY_SAVE_TABLE_EDIT_INDEXES)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_QUERY_SAVE_TABLE_EDIT_INDEXES" "\004" u8"Before you can edit the indexes of a table, you have to save it.\nDo you want to save the changes now?" ) ))); | |||
410 | if (RET_YES != xAsk->run()) | |||
411 | return; | |||
412 | ||||
413 | if (!doSaveDoc(false)) | |||
414 | return; | |||
415 | ||||
416 | OSL_ENSURE(!m_bNew && !isModified(), "OTableController::doEditIndexes: what the hell did doSaveDoc do?")do { if (true && (!(!m_bNew && !isModified()) )) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "416" ": "), "%s", "OTableController::doEditIndexes: what the hell did doSaveDoc do?" ); } } while (false); | |||
417 | } | |||
418 | ||||
419 | Reference< XNameAccess > xIndexes; // will be the keys of the table | |||
420 | Sequence< OUString > aFieldNames; // will be the column names of the table | |||
421 | try | |||
422 | { | |||
423 | // get the keys | |||
424 | Reference< XIndexesSupplier > xIndexesSupp(m_xTable, UNO_QUERY); | |||
425 | if (xIndexesSupp.is()) | |||
426 | { | |||
427 | xIndexes = xIndexesSupp->getIndexes(); | |||
428 | OSL_ENSURE(xIndexes.is(), "OTableController::doEditIndexes: no keys got from the indexes supplier!")do { if (true && (!(xIndexes.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "428" ": "), "%s", "OTableController::doEditIndexes: no keys got from the indexes supplier!" ); } } while (false); | |||
429 | } | |||
430 | else | |||
431 | OSL_FAIL("OTableController::doEditIndexes: should never have reached this (no indexes supplier)!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "431" ": "), "%s", "OTableController::doEditIndexes: should never have reached this (no indexes supplier)!" ); } } while (false); | |||
432 | ||||
433 | // get the field names | |||
434 | Reference< XColumnsSupplier > xColSupp(m_xTable, UNO_QUERY); | |||
435 | OSL_ENSURE(xColSupp.is(), "OTableController::doEditIndexes: no columns supplier!")do { if (true && (!(xColSupp.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "435" ": "), "%s", "OTableController::doEditIndexes: no columns supplier!" ); } } while (false); | |||
436 | if (xColSupp.is()) | |||
437 | { | |||
438 | Reference< XNameAccess > xCols = xColSupp->getColumns(); | |||
439 | OSL_ENSURE(xCols.is(), "OTableController::doEditIndexes: no columns!")do { if (true && (!(xCols.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "439" ": "), "%s", "OTableController::doEditIndexes: no columns!" ); } } while (false); | |||
440 | if (xCols.is()) | |||
441 | aFieldNames = xCols->getElementNames(); | |||
442 | } | |||
443 | } | |||
444 | catch( const Exception& ) | |||
445 | { | |||
446 | DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "446" ": ", "dbaccess" );; | |||
447 | } | |||
448 | ||||
449 | if (!xIndexes.is()) | |||
450 | return; | |||
451 | ||||
452 | DbaIndexDialog aDialog(getFrameWeld(), aFieldNames, xIndexes, getConnection(), getORB()); | |||
453 | if (RET_OK != aDialog.run()) | |||
454 | return; | |||
455 | ||||
456 | } | |||
457 | ||||
458 | void OTableController::impl_initialize() | |||
459 | { | |||
460 | try | |||
461 | { | |||
462 | OTableController_BASE::impl_initialize(); | |||
463 | ||||
464 | const NamedValueCollection& rArguments( getInitParams() ); | |||
465 | ||||
466 | rArguments.get_ensureType( PROPERTY_CURRENTTABLE"CurrentTable", m_sName ); | |||
467 | ||||
468 | // read autoincrement value set in the datasource | |||
469 | ::dbaui::fillAutoIncrementValue(getDataSource(),m_bAllowAutoIncrementValue,m_sAutoIncrementValue); | |||
470 | ||||
471 | assignTable(); | |||
472 | } | |||
473 | catch( const Exception& ) | |||
474 | { | |||
475 | DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "475" ": ", "dbaccess" );; | |||
476 | } | |||
477 | ||||
478 | try | |||
479 | { | |||
480 | ::dbaui::fillTypeInfo(getConnection(),m_sTypeNames,m_aTypeInfo,m_aTypeInfoIndex); // fill the needed type information | |||
481 | } | |||
482 | catch(const SQLException&) | |||
483 | { | |||
484 | OSQLWarningBox aWarning(getFrameWeld(), DBA_RES( STR_NO_TYPE_INFO_AVAILABLE)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_NO_TYPE_INFO_AVAILABLE" "\004" u8"No type information could be retrieved from the database.\nThe table design mode is not available for this data source." ) )); | |||
485 | aWarning.run(); | |||
486 | throw; | |||
487 | } | |||
488 | try | |||
489 | { | |||
490 | loadData(); // fill the column information from the table | |||
491 | getView()->initialize(); // show the windows and fill with our information | |||
492 | ClearUndoManager(); | |||
493 | setModified(false); // and we are not modified yet | |||
494 | } | |||
495 | catch( const Exception& ) | |||
496 | { | |||
497 | DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "497" ": ", "dbaccess" );; | |||
498 | } | |||
499 | } | |||
500 | ||||
501 | bool OTableController::Construct(vcl::Window* pParent) | |||
502 | { | |||
503 | setView( VclPtr<OTableDesignView>::Create( pParent, getORB(), *this ) ); | |||
| ||||
504 | OTableController_BASE::Construct(pParent); | |||
505 | return true; | |||
506 | } | |||
507 | ||||
508 | sal_Bool SAL_CALL OTableController::suspend(sal_Bool /*_bSuspend*/) | |||
509 | { | |||
510 | if ( getBroadcastHelper().bInDispose || getBroadcastHelper().bDisposed ) | |||
511 | return true; | |||
512 | ||||
513 | SolarMutexGuard aSolarGuard; | |||
514 | ::osl::MutexGuard aGuard( getMutex() ); | |||
515 | if ( getView() && getView()->IsInModalMode() ) | |||
516 | return false; | |||
517 | if ( getView() ) | |||
518 | static_cast<OTableDesignView*>(getView())->GrabFocus(); | |||
519 | bool bCheck = true; | |||
520 | if ( isModified() ) | |||
521 | { | |||
522 | if ( std::any_of(m_vRowList.begin(),m_vRowList.end(), | |||
523 | std::mem_fn(&OTableRow::isValid)) ) | |||
524 | { | |||
525 | std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(getFrameWeld(), "dbaccess/ui/tabledesignsavemodifieddialog.ui")); | |||
526 | std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("TableDesignSaveModifiedDialog")); | |||
527 | switch (xQuery->run()) | |||
528 | { | |||
529 | case RET_YES: | |||
530 | Execute(ID_BROWSER_SAVEDOC(5000 + 505),Sequence<PropertyValue>()); | |||
531 | if ( isModified() ) | |||
532 | bCheck = false; // when we save the table this must be false else some press cancel | |||
533 | break; | |||
534 | case RET_CANCEL: | |||
535 | bCheck = false; | |||
536 | break; | |||
537 | default: | |||
538 | break; | |||
539 | } | |||
540 | } | |||
541 | else if ( !m_bNew ) | |||
542 | { | |||
543 | std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(getFrameWeld(), "dbaccess/ui/deleteallrowsdialog.ui")); | |||
544 | std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("DeleteAllRowsDialog")); | |||
545 | switch (xQuery->run()) | |||
546 | { | |||
547 | case RET_YES: | |||
548 | { | |||
549 | try | |||
550 | { | |||
551 | Reference<XTablesSupplier> xTablesSup(getConnection(),UNO_QUERY); | |||
552 | Reference<XNameAccess> xTables = xTablesSup->getTables(); | |||
553 | dropTable(xTables,m_sName); | |||
554 | } | |||
555 | catch(const Exception&) | |||
556 | { | |||
557 | OSL_FAIL("OTableController::suspend: nothing is expected to happen here!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "557" ": "), "%s", "OTableController::suspend: nothing is expected to happen here!" ); } } while (false); | |||
558 | } | |||
559 | ||||
560 | } | |||
561 | break; | |||
562 | case RET_CANCEL: | |||
563 | bCheck = false; | |||
564 | break; | |||
565 | default: | |||
566 | break; | |||
567 | } | |||
568 | } | |||
569 | } | |||
570 | ||||
571 | return bCheck; | |||
572 | } | |||
573 | ||||
574 | void OTableController::describeSupportedFeatures() | |||
575 | { | |||
576 | OSingleDocumentController::describeSupportedFeatures(); | |||
577 | ||||
578 | implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO(5000 + 700), CommandGroup::EDIT ); | |||
579 | implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC(5000 + 505), CommandGroup::EDIT ); | |||
580 | implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO(5000 + 701), CommandGroup::EDIT ); | |||
581 | implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC(5000 + 500), CommandGroup::DOCUMENT ); | |||
582 | implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC(5000 + 502), CommandGroup::DOCUMENT ); | |||
583 | implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 0 ), CommandGroup::APPLICATION ); | |||
584 | implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC(5000 + 1312), CommandGroup::EDIT ); | |||
585 | implDescribeSupportedFeature( ".uno:GetUndoStrings", SID_GETUNDOSTRINGS( 10000 + 923 ) ); | |||
586 | implDescribeSupportedFeature( ".uno:GetRedoStrings", SID_GETREDOSTRINGS( 10000 + 924 ) ); | |||
587 | } | |||
588 | ||||
589 | void OTableController::impl_onModifyChanged() | |||
590 | { | |||
591 | OSingleDocumentController::impl_onModifyChanged(); | |||
592 | InvalidateFeature( SID_INDEXDESIGN( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) + 1) + 0 ) ); | |||
593 | } | |||
594 | ||||
595 | void SAL_CALL OTableController::disposing( const EventObject& _rSource ) | |||
596 | { | |||
597 | if ( _rSource.Source == m_xTable ) | |||
598 | { // some deleted our table so we have a new one | |||
599 | stopTableListening(); | |||
600 | m_xTable = nullptr; | |||
601 | m_bNew = true; | |||
602 | setModified(true); | |||
603 | } | |||
604 | else | |||
605 | OTableController_BASE::disposing( _rSource ); | |||
606 | } | |||
607 | ||||
608 | void OTableController::losingConnection( ) | |||
609 | { | |||
610 | // let the base class do its reconnect | |||
611 | OTableController_BASE::losingConnection( ); | |||
612 | ||||
613 | // remove from the table | |||
614 | Reference< XComponent > xComponent(m_xTable, UNO_QUERY); | |||
615 | if (xComponent.is()) | |||
616 | { | |||
617 | Reference<XEventListener> xEvtL( static_cast< ::cppu::OWeakObject*>(this), UNO_QUERY); | |||
618 | xComponent->removeEventListener(xEvtL); | |||
619 | } | |||
620 | stopTableListening(); | |||
621 | m_xTable = nullptr; | |||
622 | assignTable(); | |||
623 | if(!m_xTable.is()) | |||
624 | { | |||
625 | m_bNew = true; | |||
626 | setModified(true); | |||
627 | } | |||
628 | InvalidateAll(); | |||
629 | } | |||
630 | ||||
631 | TOTypeInfoSP OTableController::getTypeInfoByType(sal_Int32 _nDataType) const | |||
632 | { | |||
633 | return queryTypeInfoByType(_nDataType,m_aTypeInfo); | |||
634 | } | |||
635 | ||||
636 | void OTableController::appendColumns(Reference<XColumnsSupplier> const & _rxColSup, bool _bNew, bool _bKeyColumns) | |||
637 | { | |||
638 | try | |||
639 | { | |||
640 | // now append the columns | |||
641 | OSL_ENSURE(_rxColSup.is(),"No columns supplier")do { if (true && (!(_rxColSup.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "641" ": "), "%s", "No columns supplier"); } } while (false ); | |||
642 | if(!_rxColSup.is()) | |||
643 | return; | |||
644 | Reference<XNameAccess> xColumns = _rxColSup->getColumns(); | |||
645 | OSL_ENSURE(xColumns.is(),"No columns")do { if (true && (!(xColumns.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "645" ": "), "%s", "No columns"); } } while (false); | |||
646 | Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY); | |||
647 | ||||
648 | Reference<XAppend> xAppend(xColumns,UNO_QUERY); | |||
649 | OSL_ENSURE(xAppend.is(),"No XAppend Interface!")do { if (true && (!(xAppend.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "649" ": "), "%s", "No XAppend Interface!"); } } while ( false); | |||
650 | ||||
651 | for (auto const& row : m_vRowList) | |||
652 | { | |||
653 | OSL_ENSURE(row,"OTableRow is null!")do { if (true && (!(row))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "653" ": "), "%s", "OTableRow is null!"); } } while (false ); | |||
654 | OFieldDescription* pField = row->GetActFieldDescr(); | |||
655 | if ( !pField || (!_bNew && row->IsReadOnly() && !_bKeyColumns) ) | |||
656 | continue; | |||
657 | ||||
658 | Reference<XPropertySet> xColumn; | |||
659 | if(pField->IsPrimaryKey() || !_bKeyColumns) | |||
660 | xColumn = xColumnFactory->createDataDescriptor(); | |||
661 | if(xColumn.is()) | |||
662 | { | |||
663 | if(!_bKeyColumns) | |||
664 | ::dbaui::setColumnProperties(xColumn,pField); | |||
665 | else | |||
666 | xColumn->setPropertyValue(PROPERTY_NAME"Name",makeAny(pField->GetName())); | |||
667 | ||||
668 | xAppend->appendByDescriptor(xColumn); | |||
669 | xColumn = nullptr; | |||
670 | // now only the settings are missing | |||
671 | if(xColumns->hasByName(pField->GetName())) | |||
672 | { | |||
673 | xColumns->getByName(pField->GetName()) >>= xColumn; | |||
674 | if(xColumn.is()) | |||
675 | pField->copyColumnSettingsTo(xColumn); | |||
676 | } | |||
677 | else | |||
678 | { | |||
679 | OSL_FAIL("OTableController::appendColumns: invalid field name!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "679" ": "), "%s", "OTableController::appendColumns: invalid field name!" ); } } while (false); | |||
680 | } | |||
681 | ||||
682 | } | |||
683 | } | |||
684 | } | |||
685 | catch(const SQLException& ) | |||
686 | { | |||
687 | showError( SQLExceptionInfo( ::cppu::getCaughtException() ) ); | |||
688 | } | |||
689 | catch( const Exception& ) | |||
690 | { | |||
691 | DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "691" ": ", "dbaccess" );; | |||
692 | } | |||
693 | } | |||
694 | ||||
695 | void OTableController::appendPrimaryKey(Reference<XKeysSupplier> const & _rxSup, bool _bNew) | |||
696 | { | |||
697 | if(!_rxSup.is()) | |||
698 | return; // the database doesn't support keys | |||
699 | ||||
700 | OSL_ENSURE(_rxSup.is(),"No XKeysSupplier!")do { if (true && (!(_rxSup.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "700" ": "), "%s", "No XKeysSupplier!"); } } while (false ); | |||
701 | Reference<XIndexAccess> xKeys = _rxSup->getKeys(); | |||
702 | Reference<XPropertySet> xProp; | |||
703 | if (!xKeys.is()) | |||
704 | return; | |||
705 | const sal_Int32 nCount = xKeys->getCount(); | |||
706 | for(sal_Int32 i=0;i< nCount ;++i) | |||
707 | { | |||
708 | xKeys->getByIndex(i) >>= xProp; | |||
709 | sal_Int32 nKeyType = 0; | |||
710 | xProp->getPropertyValue(PROPERTY_TYPE"Type") >>= nKeyType; | |||
711 | if(KeyType::PRIMARY == nKeyType) | |||
712 | { | |||
713 | return; // primary key already exists after appending a column | |||
714 | } | |||
715 | } | |||
716 | Reference<XDataDescriptorFactory> xKeyFactory(xKeys,UNO_QUERY); | |||
717 | OSL_ENSURE(xKeyFactory.is(),"No XDataDescriptorFactory Interface!")do { if (true && (!(xKeyFactory.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "717" ": "), "%s", "No XDataDescriptorFactory Interface!" ); } } while (false); | |||
718 | if ( !xKeyFactory.is() ) | |||
719 | return; | |||
720 | Reference<XAppend> xAppend(xKeyFactory,UNO_QUERY); | |||
721 | OSL_ENSURE(xAppend.is(),"No XAppend Interface!")do { if (true && (!(xAppend.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "721" ": "), "%s", "No XAppend Interface!"); } } while ( false); | |||
722 | ||||
723 | Reference<XPropertySet> xKey = xKeyFactory->createDataDescriptor(); | |||
724 | OSL_ENSURE(xKey.is(),"Key is null!")do { if (true && (!(xKey.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "724" ": "), "%s", "Key is null!"); } } while (false); | |||
725 | xKey->setPropertyValue(PROPERTY_TYPE"Type",makeAny(KeyType::PRIMARY)); | |||
726 | ||||
727 | Reference<XColumnsSupplier> xColSup(xKey,UNO_QUERY); | |||
728 | if(xColSup.is()) | |||
729 | { | |||
730 | appendColumns(xColSup,_bNew,true); | |||
731 | Reference<XNameAccess> xColumns = xColSup->getColumns(); | |||
732 | if(xColumns->hasElements()) | |||
733 | xAppend->appendByDescriptor(xKey); | |||
734 | } | |||
735 | } | |||
736 | ||||
737 | void OTableController::loadData() | |||
738 | { | |||
739 | // if the data structure already exists, empty it | |||
740 | m_vRowList.clear(); | |||
741 | ||||
742 | std::shared_ptr<OTableRow> pTabEdRow; | |||
743 | Reference< XDatabaseMetaData> xMetaData = getMetaData( ); | |||
744 | // fill data structure with data from DataDefinitionObject | |||
745 | if(m_xTable.is() && xMetaData.is()) | |||
746 | { | |||
747 | Reference<XColumnsSupplier> xColSup(m_xTable,UNO_QUERY); | |||
748 | OSL_ENSURE(xColSup.is(),"No XColumnsSupplier!")do { if (true && (!(xColSup.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "748" ": "), "%s", "No XColumnsSupplier!"); } } while (false ); | |||
749 | Reference<XNameAccess> xColumns = xColSup->getColumns(); | |||
750 | // ReadOnly-Flag | |||
751 | // For Drop no row may be editable | |||
752 | // For Add only the empty rows may be editable | |||
753 | // For Add and Drop all rows can be edited | |||
754 | // sal_Bool bReadOldRow = xMetaData->supportsAlterTableWithAddColumn() && xMetaData->supportsAlterTableWithDropColumn(); | |||
755 | bool bIsAlterAllowed = isAlterAllowed(); | |||
756 | ||||
757 | const Sequence<OUString> aColNames = xColumns->getElementNames(); | |||
758 | for(const OUString& rColumn : aColNames) | |||
759 | { | |||
760 | Reference<XPropertySet> xColumn; | |||
761 | xColumns->getByName(rColumn) >>= xColumn; | |||
762 | sal_Int32 nType = 0; | |||
763 | sal_Int32 nScale = 0; | |||
764 | sal_Int32 nPrecision = 0; | |||
765 | sal_Int32 nNullable = 0; | |||
766 | sal_Int32 nFormatKey = 0; | |||
767 | sal_Int32 nAlign = 0; | |||
768 | ||||
769 | bool bIsAutoIncrement = false, bIsCurrency = false; | |||
770 | OUString sName,sDescription,sTypeName,sHelpText; | |||
771 | Any aControlDefault; | |||
772 | ||||
773 | // get the properties from the column | |||
774 | xColumn->getPropertyValue(PROPERTY_NAME"Name") >>= sName; | |||
775 | xColumn->getPropertyValue(PROPERTY_TYPENAME"TypeName") >>= sTypeName; | |||
776 | xColumn->getPropertyValue(PROPERTY_ISNULLABLE"IsNullable") >>= nNullable; | |||
777 | xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT"IsAutoIncrement") >>= bIsAutoIncrement; | |||
778 | xColumn->getPropertyValue(PROPERTY_ISCURRENCY"IsCurrency") >>= bIsCurrency; | |||
779 | xColumn->getPropertyValue(PROPERTY_TYPE"Type") >>= nType; | |||
780 | xColumn->getPropertyValue(PROPERTY_SCALE"Scale") >>= nScale; | |||
781 | xColumn->getPropertyValue(PROPERTY_PRECISION"Precision") >>= nPrecision; | |||
782 | xColumn->getPropertyValue(PROPERTY_DESCRIPTION"Description") >>= sDescription; | |||
783 | ||||
784 | if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_HELPTEXT"HelpText")) | |||
785 | xColumn->getPropertyValue(PROPERTY_HELPTEXT"HelpText") >>= sHelpText; | |||
786 | ||||
787 | if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_CONTROLDEFAULT"ControlDefault")) | |||
788 | aControlDefault = xColumn->getPropertyValue(PROPERTY_CONTROLDEFAULT"ControlDefault"); | |||
789 | if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_FORMATKEY"FormatKey")) | |||
790 | xColumn->getPropertyValue(PROPERTY_FORMATKEY"FormatKey") >>= nFormatKey; | |||
791 | if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_ALIGN"Align")) | |||
792 | xColumn->getPropertyValue(PROPERTY_ALIGN"Align") >>= nAlign; | |||
793 | ||||
794 | pTabEdRow = std::make_shared<OTableRow>(); | |||
795 | pTabEdRow->SetReadOnly(!bIsAlterAllowed); | |||
796 | // search for type | |||
797 | bool bForce; | |||
798 | TOTypeInfoSP pTypeInfo = ::dbaui::getTypeInfoFromType(m_aTypeInfo,nType,sTypeName,"x",nPrecision,nScale,bIsAutoIncrement,bForce); | |||
799 | if ( !pTypeInfo ) | |||
800 | pTypeInfo = m_pTypeInfo; | |||
801 | pTabEdRow->SetFieldType( pTypeInfo, bForce ); | |||
802 | ||||
803 | OFieldDescription* pActFieldDescr = pTabEdRow->GetActFieldDescr(); | |||
804 | OSL_ENSURE(pActFieldDescr, "OTableController::loadData: invalid field description generated by the table row!")do { if (true && (!(pActFieldDescr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "804" ": "), "%s", "OTableController::loadData: invalid field description generated by the table row!" ); } } while (false); | |||
805 | if ( pActFieldDescr ) | |||
806 | { | |||
807 | pActFieldDescr->SetName(sName); | |||
808 | pActFieldDescr->SetFormatKey(nFormatKey); | |||
809 | pActFieldDescr->SetDescription(sDescription); | |||
810 | pActFieldDescr->SetHelpText(sHelpText); | |||
811 | pActFieldDescr->SetAutoIncrement(bIsAutoIncrement); | |||
812 | pActFieldDescr->SetHorJustify(dbaui::mapTextJustify(nAlign)); | |||
813 | pActFieldDescr->SetCurrency(bIsCurrency); | |||
814 | ||||
815 | // special data | |||
816 | pActFieldDescr->SetIsNullable(nNullable); | |||
817 | pActFieldDescr->SetControlDefault(aControlDefault); | |||
818 | pActFieldDescr->SetPrecision(nPrecision); | |||
819 | pActFieldDescr->SetScale(nScale); | |||
820 | } | |||
821 | m_vRowList.push_back( pTabEdRow); | |||
822 | } | |||
823 | // fill the primary key information | |||
824 | Reference<XNameAccess> xKeyColumns = getKeyColumns(); | |||
825 | if(xKeyColumns.is()) | |||
826 | { | |||
827 | const Sequence<OUString> aKeyColumnNames = xKeyColumns->getElementNames(); | |||
828 | for(const OUString& rKeyColumn : aKeyColumnNames) | |||
829 | { | |||
830 | for(std::shared_ptr<OTableRow> const& pRow : m_vRowList) | |||
831 | { | |||
832 | if(pRow->GetActFieldDescr()->GetName() == rKeyColumn) | |||
833 | { | |||
834 | pRow->SetPrimaryKey(true); | |||
835 | break; | |||
836 | } | |||
837 | } | |||
838 | } | |||
839 | } | |||
840 | } | |||
841 | ||||
842 | // fill empty rows | |||
843 | ||||
844 | OTypeInfoMap::const_iterator aTypeIter = m_aTypeInfo.find(DataType::VARCHAR); | |||
845 | if(aTypeIter == m_aTypeInfo.end()) | |||
846 | aTypeIter = m_aTypeInfo.begin(); | |||
847 | ||||
848 | OSL_ENSURE(aTypeIter != m_aTypeInfo.end(),"We have no type information!")do { if (true && (!(aTypeIter != m_aTypeInfo.end()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "848" ": "), "%s", "We have no type information!"); } } while (false); | |||
849 | ||||
850 | bool bReadRow = !isAddAllowed(); | |||
851 | for(sal_Int32 i=m_vRowList.size(); i < NEWCOLS128; i++ ) | |||
852 | { | |||
853 | pTabEdRow = std::make_shared<OTableRow>(); | |||
854 | pTabEdRow->SetReadOnly(bReadRow); | |||
855 | m_vRowList.push_back( pTabEdRow); | |||
856 | } | |||
857 | } | |||
858 | ||||
859 | Reference<XNameAccess> OTableController::getKeyColumns() const | |||
860 | { | |||
861 | return getPrimaryKeyColumns_throw(m_xTable); | |||
862 | } | |||
863 | ||||
864 | bool OTableController::checkColumns(bool _bNew) | |||
865 | { | |||
866 | bool bOk = true; | |||
867 | bool bFoundPKey = false; | |||
868 | Reference< XDatabaseMetaData > xMetaData = getMetaData( ); | |||
869 | DatabaseMetaData aMetaData( getConnection() ); | |||
870 | ||||
871 | ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers()); | |||
872 | std::vector< std::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin(); | |||
873 | std::vector< std::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end(); | |||
874 | for(;aIter != aEnd;++aIter) | |||
875 | { | |||
876 | OFieldDescription* pFieldDesc = (*aIter)->GetActFieldDescr(); | |||
877 | if (pFieldDesc && !pFieldDesc->GetName().isEmpty()) | |||
878 | { | |||
879 | bFoundPKey |= (*aIter)->IsPrimaryKey(); | |||
880 | // first check for duplicate names | |||
881 | bool bDuplicateNameFound = std::any_of(aIter+1, aEnd, | |||
882 | [&bCase, &pFieldDesc](const std::shared_ptr<OTableRow>& rxRow) { | |||
883 | OFieldDescription* pCompareDesc = rxRow->GetActFieldDescr(); | |||
884 | return pCompareDesc && bCase(pCompareDesc->GetName(),pFieldDesc->GetName()); | |||
885 | }); | |||
886 | if (bDuplicateNameFound) | |||
887 | { | |||
888 | OUString strMessage = DBA_RES(STR_TABLEDESIGN_DUPLICATE_NAME)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_DUPLICATE_NAME" "\004" u8"The table cannot be saved because column name \"$column$\" was assigned twice." ) ); | |||
889 | strMessage = strMessage.replaceFirst("$column$", pFieldDesc->GetName()); | |||
890 | OSQLWarningBox aWarning(getFrameWeld(), strMessage); | |||
891 | aWarning.run(); | |||
892 | return false; | |||
893 | } | |||
894 | } | |||
895 | } | |||
896 | if ( _bNew && !bFoundPKey && aMetaData.supportsPrimaryKeys() ) | |||
897 | { | |||
898 | OUString sTitle(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY_HEAD)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_NO_PRIM_KEY_HEAD" "\004" u8"No primary key" ) )); | |||
899 | OUString sMsg(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_NO_PRIM_KEY" "\004" u8"A unique index or primary key is required for data record identification in this database.\nYou can only enter data into this table when one of these two structural conditions has been met.\n\nShould a primary key be created now?" ) )); | |||
900 | OSQLMessageBox aBox(getFrameWeld(), sTitle,sMsg, MessBoxStyle::YesNoCancel | MessBoxStyle::DefaultYes); | |||
901 | ||||
902 | switch (aBox.run()) | |||
903 | { | |||
904 | case RET_YES: | |||
905 | { | |||
906 | auto pNewRow = std::make_shared<OTableRow>(); | |||
907 | TOTypeInfoSP pTypeInfo = ::dbaui::queryPrimaryKeyType(m_aTypeInfo); | |||
908 | if ( !pTypeInfo ) | |||
909 | break; | |||
910 | ||||
911 | pNewRow->SetFieldType( pTypeInfo ); | |||
912 | OFieldDescription* pActFieldDescr = pNewRow->GetActFieldDescr(); | |||
913 | ||||
914 | pActFieldDescr->SetAutoIncrement(false); | |||
915 | pActFieldDescr->SetIsNullable(ColumnValue::NO_NULLS); | |||
916 | ||||
917 | pActFieldDescr->SetName( createUniqueName("ID" )); | |||
918 | pActFieldDescr->SetPrimaryKey( true ); | |||
919 | m_vRowList.insert(m_vRowList.begin(),pNewRow); | |||
920 | ||||
921 | static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->Invalidate(); | |||
922 | static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->RowInserted(0); | |||
923 | } | |||
924 | break; | |||
925 | case RET_CANCEL: | |||
926 | bOk = false; | |||
927 | break; | |||
928 | } | |||
929 | } | |||
930 | return bOk; | |||
931 | } | |||
932 | ||||
933 | void OTableController::alterColumns() | |||
934 | { | |||
935 | Reference<XColumnsSupplier> xColSup(m_xTable,UNO_QUERY_THROW); | |||
936 | ||||
937 | Reference<XNameAccess> xColumns = xColSup->getColumns(); | |||
938 | Reference<XIndexAccess> xIdxColumns(xColumns,UNO_QUERY_THROW); | |||
939 | OSL_ENSURE(xColumns.is(),"No columns")do { if (true && (!(xColumns.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "939" ": "), "%s", "No columns"); } } while (false); | |||
940 | if ( !xColumns.is() ) | |||
941 | return; | |||
942 | Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY); // can be null | |||
943 | ||||
944 | sal_Int32 nColumnCount = xIdxColumns->getCount(); | |||
945 | Reference<XDrop> xDrop(xColumns,UNO_QUERY); // can be null | |||
946 | Reference<XAppend> xAppend(xColumns,UNO_QUERY); // can be null | |||
947 | Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY); // can be null | |||
948 | ||||
949 | bool bReload = false; // refresh the data | |||
950 | ||||
951 | // contains all columns names which are already handled those which are not in the list will be deleted | |||
952 | Reference< XDatabaseMetaData> xMetaData = getMetaData( ); | |||
953 | ||||
954 | std::set<OUString, comphelper::UStringMixLess> aColumns( | |||
955 | comphelper::UStringMixLess( | |||
956 | !xMetaData.is() | |||
957 | || xMetaData->supportsMixedCaseQuotedIdentifiers())); | |||
958 | std::vector< std::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin(); | |||
959 | std::vector< std::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end(); | |||
960 | // first look for columns where something other than the name changed | |||
961 | for(sal_Int32 nPos = 0;aIter != aEnd;++aIter,++nPos) | |||
962 | { | |||
963 | OSL_ENSURE(*aIter,"OTableRow is null!")do { if (true && (!(*aIter))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "963" ": "), "%s", "OTableRow is null!"); } } while (false ); | |||
964 | OFieldDescription* pField = (*aIter)->GetActFieldDescr(); | |||
965 | if ( !pField ) | |||
966 | continue; | |||
967 | if ( (*aIter)->IsReadOnly() ) | |||
968 | { | |||
969 | aColumns.insert(pField->GetName()); | |||
970 | continue; | |||
971 | } | |||
972 | ||||
973 | Reference<XPropertySet> xColumn; | |||
974 | if ( xColumns->hasByName(pField->GetName()) ) | |||
975 | { | |||
976 | aColumns.insert(pField->GetName()); | |||
977 | xColumns->getByName(pField->GetName()) >>= xColumn; | |||
978 | OSL_ENSURE(xColumn.is(),"Column is null!")do { if (true && (!(xColumn.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "978" ": "), "%s", "Column is null!"); } } while (false); | |||
979 | ||||
980 | sal_Int32 nType=0,nPrecision=0,nScale=0,nNullable=0; | |||
981 | bool bAutoIncrement = false; | |||
982 | OUString sTypeName,sDescription; | |||
983 | ||||
984 | xColumn->getPropertyValue(PROPERTY_TYPE"Type") >>= nType; | |||
985 | xColumn->getPropertyValue(PROPERTY_PRECISION"Precision") >>= nPrecision; | |||
986 | xColumn->getPropertyValue(PROPERTY_SCALE"Scale") >>= nScale; | |||
987 | xColumn->getPropertyValue(PROPERTY_ISNULLABLE"IsNullable") >>= nNullable; | |||
988 | xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT"IsAutoIncrement") >>= bAutoIncrement; | |||
989 | xColumn->getPropertyValue(PROPERTY_DESCRIPTION"Description") >>= sDescription; | |||
990 | ||||
991 | try { xColumn->getPropertyValue(PROPERTY_TYPENAME"TypeName") >>= sTypeName; } | |||
992 | catch( const Exception& ) | |||
993 | { | |||
994 | OSL_FAIL( "no TypeName property?!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "994" ": "), "%s", "no TypeName property?!"); } } while ( false); | |||
995 | // since this is a last minute fix for #i41785#, I want to be on the safe side, | |||
996 | // and catch errors here as early as possible (instead of the whole process of altering | |||
997 | // the columns failing) | |||
998 | // Normally, sdbcx::Column objects are expected to have a TypeName property | |||
999 | } | |||
1000 | ||||
1001 | // check if something changed | |||
1002 | if((nType != pField->GetType() || | |||
1003 | sTypeName != pField->GetTypeName() || | |||
1004 | (nPrecision != pField->GetPrecision() && nPrecision ) || | |||
1005 | nScale != pField->GetScale() || | |||
1006 | nNullable != pField->GetIsNullable() || | |||
1007 | sDescription != pField->GetDescription() || | |||
1008 | bAutoIncrement != pField->IsAutoIncrement())&& | |||
1009 | xColumnFactory.is()) | |||
1010 | { | |||
1011 | Reference<XPropertySet> xNewColumn = xColumnFactory->createDataDescriptor(); | |||
1012 | ::dbaui::setColumnProperties(xNewColumn,pField); | |||
1013 | // first try to alter the column | |||
1014 | bool bNotOk = false; | |||
1015 | try | |||
1016 | { | |||
1017 | // first try if we can alter the column | |||
1018 | if(xAlter.is()) | |||
1019 | xAlter->alterColumnByName(pField->GetName(),xNewColumn); | |||
1020 | } | |||
1021 | catch(const SQLException&) | |||
1022 | { | |||
1023 | if(xDrop.is() && xAppend.is()) | |||
1024 | { | |||
1025 | OUString aMessage( DBA_RES( STR_TABLEDESIGN_ALTER_ERROR )::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_ALTER_ERROR" "\004" u8"The column \"$column$\" could not be changed. Should the column instead be deleted and the new format appended?" ) ) ); | |||
1026 | aMessage = aMessage.replaceFirst( "$column$", pField->GetName() ); | |||
1027 | ||||
1028 | SQLExceptionInfo aError( ::cppu::getCaughtException() ); | |||
1029 | OSQLWarningBox aMsg(getFrameWeld(), aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes , &aError); | |||
1030 | bNotOk = aMsg.run() == RET_YES; | |||
1031 | } | |||
1032 | else | |||
1033 | throw; | |||
1034 | } | |||
1035 | // if something went wrong or we can't alter columns | |||
1036 | // drop and append a new one | |||
1037 | if((!xAlter.is() || bNotOk) && xDrop.is() && xAppend.is()) | |||
1038 | { | |||
1039 | xDrop->dropByName(pField->GetName()); | |||
1040 | try | |||
1041 | { | |||
1042 | xAppend->appendByDescriptor(xNewColumn); | |||
1043 | } | |||
1044 | catch(const SQLException&) | |||
1045 | { // an error occurred so we try to reactivate the old one | |||
1046 | xAppend->appendByDescriptor(xColumn); | |||
1047 | throw; | |||
1048 | } | |||
1049 | } | |||
1050 | // exceptions are caught outside | |||
1051 | xNewColumn = nullptr; | |||
1052 | if(xColumns->hasByName(pField->GetName())) | |||
1053 | xColumns->getByName(pField->GetName()) >>= xColumn; | |||
1054 | bReload = true; | |||
1055 | } | |||
1056 | ||||
1057 | } | |||
1058 | else if(xColumnFactory.is() && xAlter.is() && nPos < nColumnCount) | |||
1059 | { // we can't find the column so we could try it with the index before we drop and append a new column | |||
1060 | try | |||
1061 | { | |||
1062 | Reference<XPropertySet> xNewColumn = xColumnFactory->createDataDescriptor(); | |||
1063 | ::dbaui::setColumnProperties(xNewColumn,pField); | |||
1064 | xAlter->alterColumnByIndex(nPos,xNewColumn); | |||
1065 | if(xColumns->hasByName(pField->GetName())) | |||
1066 | { // ask for the append by name | |||
1067 | aColumns.insert(pField->GetName()); | |||
1068 | xColumns->getByName(pField->GetName()) >>= xColumn; | |||
1069 | if(xColumn.is()) | |||
1070 | pField->copyColumnSettingsTo(xColumn); | |||
1071 | } | |||
1072 | else | |||
1073 | { | |||
1074 | OSL_FAIL("OTableController::alterColumns: invalid column (2)!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1074" ": "), "%s", "OTableController::alterColumns: invalid column (2)!" ); } } while (false); | |||
1075 | } | |||
1076 | } | |||
1077 | catch(const SQLException&) | |||
1078 | { // we couldn't alter the column so we have to add new columns | |||
1079 | SQLExceptionInfo aError( ::cppu::getCaughtException() ); | |||
1080 | bReload = true; | |||
1081 | if(xDrop.is() && xAppend.is()) | |||
1082 | { | |||
1083 | OUString aMessage(DBA_RES(STR_TABLEDESIGN_ALTER_ERROR)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_ALTER_ERROR" "\004" u8"The column \"$column$\" could not be changed. Should the column instead be deleted and the new format appended?" ) )); | |||
1084 | aMessage = aMessage.replaceFirst("$column$",pField->GetName()); | |||
1085 | OSQLWarningBox aMsg(getFrameWeld(), aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, &aError); | |||
1086 | if (aMsg.run() != RET_YES) | |||
1087 | { | |||
1088 | Reference<XPropertySet> xNewColumn(xIdxColumns->getByIndex(nPos),UNO_QUERY_THROW); | |||
1089 | OUString sName; | |||
1090 | xNewColumn->getPropertyValue(PROPERTY_NAME"Name") >>= sName; | |||
1091 | aColumns.insert(sName); | |||
1092 | aColumns.insert(pField->GetName()); | |||
1093 | continue; | |||
1094 | } | |||
1095 | } | |||
1096 | else | |||
1097 | throw; | |||
1098 | } | |||
1099 | } | |||
1100 | else | |||
1101 | bReload = true; | |||
1102 | } | |||
1103 | // alter column settings | |||
1104 | ||||
1105 | // first look for columns where something other than the name changed | |||
1106 | for (auto const& row : m_vRowList) | |||
1107 | { | |||
1108 | OSL_ENSURE(row,"OTableRow is null!")do { if (true && (!(row))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1108" ": "), "%s", "OTableRow is null!"); } } while (false ); | |||
1109 | OFieldDescription* pField = row->GetActFieldDescr(); | |||
1110 | if ( !pField ) | |||
1111 | continue; | |||
1112 | if ( row->IsReadOnly() ) | |||
1113 | { | |||
1114 | aColumns.insert(pField->GetName()); | |||
1115 | continue; | |||
1116 | } | |||
1117 | ||||
1118 | Reference<XPropertySet> xColumn; | |||
1119 | if ( xColumns->hasByName(pField->GetName()) ) | |||
1120 | { | |||
1121 | xColumns->getByName(pField->GetName()) >>= xColumn; | |||
1122 | Reference<XPropertySetInfo> xInfo = xColumn->getPropertySetInfo(); | |||
1123 | if ( xInfo->hasPropertyByName(PROPERTY_HELPTEXT"HelpText") ) | |||
1124 | xColumn->setPropertyValue(PROPERTY_HELPTEXT"HelpText",makeAny(pField->GetHelpText())); | |||
1125 | ||||
1126 | if(xInfo->hasPropertyByName(PROPERTY_CONTROLDEFAULT"ControlDefault")) | |||
1127 | xColumn->setPropertyValue(PROPERTY_CONTROLDEFAULT"ControlDefault",pField->GetControlDefault()); | |||
1128 | if(xInfo->hasPropertyByName(PROPERTY_FORMATKEY"FormatKey")) | |||
1129 | xColumn->setPropertyValue(PROPERTY_FORMATKEY"FormatKey",makeAny(pField->GetFormatKey())); | |||
1130 | if(xInfo->hasPropertyByName(PROPERTY_ALIGN"Align")) | |||
1131 | xColumn->setPropertyValue(PROPERTY_ALIGN"Align",makeAny(dbaui::mapTextAllign(pField->GetHorJustify()))); | |||
1132 | } | |||
1133 | } | |||
1134 | // second drop all columns which could be found by name | |||
1135 | Reference<XNameAccess> xKeyColumns = getKeyColumns(); | |||
1136 | // now we have to look for the columns who could be deleted | |||
1137 | if ( xDrop.is() ) | |||
1138 | { | |||
1139 | const Sequence<OUString> aColNames = xColumns->getElementNames(); | |||
1140 | for(const OUString& rColumnName : aColNames) | |||
1141 | { | |||
1142 | if(aColumns.find(rColumnName) == aColumns.end()) // found a column to delete | |||
1143 | { | |||
1144 | if(xKeyColumns.is() && xKeyColumns->hasByName(rColumnName)) // check if this column is a member of the primary key | |||
1145 | { | |||
1146 | OUString aMsgT(DBA_RES(STR_TBL_COLUMN_IS_KEYCOLUMN)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TBL_COLUMN_IS_KEYCOLUMN" "\004" u8"The column \"$column$\" belongs to the primary key. If the column is deleted, the primary key will also be deleted. Do you really want to continue?" ) )); | |||
1147 | aMsgT = aMsgT.replaceFirst("$column$",rColumnName); | |||
1148 | OUString aTitle(DBA_RES(STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE" "\004" u8"Primary Key Affected" ) )); | |||
1149 | OSQLMessageBox aMsg(getFrameWeld(), aTitle, aMsgT, MessBoxStyle::YesNo| MessBoxStyle::DefaultYes); | |||
1150 | if (aMsg.run() == RET_YES) | |||
1151 | { | |||
1152 | xKeyColumns = nullptr; | |||
1153 | dropPrimaryKey(); | |||
1154 | } | |||
1155 | else | |||
1156 | { | |||
1157 | bReload = true; | |||
1158 | continue; | |||
1159 | } | |||
1160 | } | |||
1161 | try | |||
1162 | { | |||
1163 | xDrop->dropByName(rColumnName); | |||
1164 | } | |||
1165 | catch (const SQLException&) | |||
1166 | { | |||
1167 | OUString sError( DBA_RES( STR_TABLEDESIGN_COULD_NOT_DROP_COL )::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TABLEDESIGN_COULD_NOT_DROP_COL" "\004" u8"The column $column$ could not be deleted." ) ) ); | |||
1168 | sError = sError.replaceFirst( "$column$", rColumnName ); | |||
1169 | ||||
1170 | SQLException aNewException; | |||
1171 | aNewException.Message = sError; | |||
1172 | aNewException.SQLState = "S1000"; | |||
1173 | aNewException.NextException = ::cppu::getCaughtException(); | |||
1174 | ||||
1175 | throw aNewException; | |||
1176 | } | |||
1177 | } | |||
1178 | } | |||
1179 | } | |||
1180 | ||||
1181 | // third append the new columns | |||
1182 | for(const auto& rxRow : m_vRowList) | |||
1183 | { | |||
1184 | OSL_ENSURE(rxRow,"OTableRow is null!")do { if (true && (!(rxRow))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1184" ": "), "%s", "OTableRow is null!"); } } while (false ); | |||
1185 | OFieldDescription* pField = rxRow->GetActFieldDescr(); | |||
1186 | if ( !pField || rxRow->IsReadOnly() || aColumns.find(pField->GetName()) != aColumns.end() ) | |||
1187 | continue; | |||
1188 | ||||
1189 | Reference<XPropertySet> xColumn; | |||
1190 | if(!xColumns->hasByName(pField->GetName())) | |||
1191 | { | |||
1192 | if(xColumnFactory.is() && xAppend.is()) | |||
1193 | {// column not found by its name so we assume it is new | |||
1194 | // Column is new | |||
1195 | xColumn = xColumnFactory->createDataDescriptor(); | |||
1196 | ::dbaui::setColumnProperties(xColumn,pField); | |||
1197 | xAppend->appendByDescriptor(xColumn); | |||
1198 | if(xColumns->hasByName(pField->GetName())) | |||
1199 | { // ask for the append by name | |||
1200 | aColumns.insert(pField->GetName()); | |||
1201 | xColumns->getByName(pField->GetName()) >>= xColumn; | |||
1202 | if(xColumn.is()) | |||
1203 | pField->copyColumnSettingsTo(xColumn); | |||
1204 | } | |||
1205 | else | |||
1206 | { | |||
1207 | OSL_FAIL("OTableController::alterColumns: invalid column!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1207" ": "), "%s", "OTableController::alterColumns: invalid column!" ); } } while (false); | |||
1208 | } | |||
1209 | } | |||
1210 | } | |||
1211 | } | |||
1212 | ||||
1213 | // check if we have to do something with the primary key | |||
1214 | bool bNeedDropKey = false; | |||
1215 | bool bNeedAppendKey = false; | |||
1216 | if ( xKeyColumns.is() ) | |||
1217 | { | |||
1218 | for(const auto& rxRow : m_vRowList) | |||
1219 | { | |||
1220 | OSL_ENSURE(rxRow,"OTableRow is null!")do { if (true && (!(rxRow))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1220" ": "), "%s", "OTableRow is null!"); } } while (false ); | |||
1221 | OFieldDescription* pField = rxRow->GetActFieldDescr(); | |||
1222 | if ( !pField ) | |||
1223 | continue; | |||
1224 | ||||
1225 | if ( pField->IsPrimaryKey() | |||
1226 | && !xKeyColumns->hasByName( pField->GetName() ) | |||
1227 | ) | |||
1228 | { // new primary key column inserted which isn't already in the columns selection | |||
1229 | bNeedDropKey = bNeedAppendKey = true; | |||
1230 | break; | |||
1231 | } | |||
1232 | else if ( !pField->IsPrimaryKey() | |||
1233 | && xKeyColumns->hasByName( pField->GetName() ) | |||
1234 | ) | |||
1235 | { // found a column which currently is in the primary key, but is marked not to be anymore | |||
1236 | bNeedDropKey = bNeedAppendKey = true; | |||
1237 | break; | |||
1238 | } | |||
1239 | } | |||
1240 | } | |||
1241 | else | |||
1242 | { // no primary key available so we check if we should create one | |||
1243 | bNeedAppendKey = true; | |||
1244 | } | |||
1245 | ||||
1246 | if ( bNeedDropKey && xKeyColumns.is() && xKeyColumns->getElementNames().hasElements() ) | |||
1247 | dropPrimaryKey(); | |||
1248 | ||||
1249 | if ( bNeedAppendKey ) | |||
1250 | { | |||
1251 | Reference< XKeysSupplier > xKeySup( m_xTable, UNO_QUERY ); | |||
1252 | appendPrimaryKey( xKeySup ,false); | |||
1253 | } | |||
1254 | ||||
1255 | reSyncRows(); | |||
1256 | ||||
1257 | if ( bReload ) | |||
1258 | reload(); | |||
1259 | } | |||
1260 | ||||
1261 | void OTableController::dropPrimaryKey() | |||
1262 | { | |||
1263 | SQLExceptionInfo aInfo; | |||
1264 | try | |||
1265 | { | |||
1266 | Reference<XKeysSupplier> xKeySup(m_xTable,UNO_QUERY); | |||
1267 | Reference<XIndexAccess> xKeys; | |||
1268 | if(xKeySup.is()) | |||
1269 | xKeys = xKeySup->getKeys(); | |||
1270 | ||||
1271 | if(xKeys.is()) | |||
1272 | { | |||
1273 | Reference<XPropertySet> xProp; | |||
1274 | for(sal_Int32 i=0;i< xKeys->getCount();++i) | |||
1275 | { | |||
1276 | xProp.set(xKeys->getByIndex(i),UNO_QUERY); | |||
1277 | sal_Int32 nKeyType = 0; | |||
1278 | xProp->getPropertyValue(PROPERTY_TYPE"Type") >>= nKeyType; | |||
1279 | if(KeyType::PRIMARY == nKeyType) | |||
1280 | { | |||
1281 | Reference<XDrop> xDrop(xKeys,UNO_QUERY); | |||
1282 | xDrop->dropByIndex(i); // delete the key | |||
1283 | break; | |||
1284 | } | |||
1285 | } | |||
1286 | } | |||
1287 | } | |||
1288 | catch(const SQLContext& e) | |||
1289 | { | |||
1290 | aInfo = SQLExceptionInfo(e); | |||
1291 | } | |||
1292 | catch(const SQLWarning& e) | |||
1293 | { | |||
1294 | aInfo = SQLExceptionInfo(e); | |||
1295 | } | |||
1296 | catch(const SQLException& e) | |||
1297 | { | |||
1298 | aInfo = SQLExceptionInfo(e); | |||
1299 | } | |||
1300 | catch( const Exception& ) | |||
1301 | { | |||
1302 | DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1302" ": ", "dbaccess" );; | |||
1303 | } | |||
1304 | ||||
1305 | showError(aInfo); | |||
1306 | } | |||
1307 | ||||
1308 | void OTableController::assignTable() | |||
1309 | { | |||
1310 | // get the table | |||
1311 | if(m_sName.isEmpty()) | |||
1312 | return; | |||
1313 | ||||
1314 | Reference<XNameAccess> xNameAccess; | |||
1315 | Reference<XTablesSupplier> xSup(getConnection(),UNO_QUERY); | |||
1316 | if(!xSup.is()) | |||
1317 | return; | |||
1318 | ||||
1319 | xNameAccess = xSup->getTables(); | |||
1320 | OSL_ENSURE(xNameAccess.is(),"no nameaccess for the queries!")do { if (true && (!(xNameAccess.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1320" ": "), "%s", "no nameaccess for the queries!"); } } while (false); | |||
1321 | ||||
1322 | if(!xNameAccess->hasByName(m_sName)) | |||
1323 | return; | |||
1324 | ||||
1325 | Reference<XPropertySet> xProp(xNameAccess->getByName(m_sName), css::uno::UNO_QUERY); | |||
1326 | if (!xProp.is()) | |||
1327 | return; | |||
1328 | ||||
1329 | m_xTable = xProp; | |||
1330 | startTableListening(); | |||
1331 | ||||
1332 | // check if we set the table editable | |||
1333 | Reference<XDatabaseMetaData> xMeta = getConnection()->getMetaData(); | |||
1334 | setEditable( xMeta.is() && !xMeta->isReadOnly() && (isAlterAllowed() || isDropAllowed() || isAddAllowed()) ); | |||
1335 | if(!isEditable()) | |||
1336 | { | |||
1337 | for( const auto& rTableRow : m_vRowList ) | |||
1338 | { | |||
1339 | rTableRow->SetReadOnly(); | |||
1340 | } | |||
1341 | } | |||
1342 | m_bNew = false; | |||
1343 | // be notified when the table is in disposing | |||
1344 | InvalidateAll(); | |||
1345 | } | |||
1346 | ||||
1347 | bool OTableController::isAddAllowed() const | |||
1348 | { | |||
1349 | Reference<XColumnsSupplier> xColsSup(m_xTable,UNO_QUERY); | |||
1350 | bool bAddAllowed = !m_xTable.is(); | |||
1351 | if(xColsSup.is()) | |||
1352 | bAddAllowed = Reference<XAppend>(xColsSup->getColumns(),UNO_QUERY).is(); | |||
1353 | ||||
1354 | try | |||
1355 | { | |||
1356 | Reference< XDatabaseMetaData > xMetaData = getMetaData( ); | |||
1357 | bAddAllowed = bAddAllowed || ( xMetaData.is() && xMetaData->supportsAlterTableWithAddColumn()); | |||
1358 | } | |||
1359 | catch(Exception&) | |||
1360 | { | |||
1361 | DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1361" ": ", "dbaccess" );; | |||
1362 | bAddAllowed = false; | |||
1363 | } | |||
1364 | ||||
1365 | return bAddAllowed; | |||
1366 | } | |||
1367 | ||||
1368 | bool OTableController::isDropAllowed() const | |||
1369 | { | |||
1370 | Reference<XColumnsSupplier> xColsSup(m_xTable,UNO_QUERY); | |||
1371 | bool bDropAllowed = !m_xTable.is(); | |||
1372 | if(xColsSup.is()) | |||
1373 | { | |||
1374 | Reference<XNameAccess> xNameAccess = xColsSup->getColumns(); | |||
1375 | bDropAllowed = Reference<XDrop>(xNameAccess,UNO_QUERY).is() && xNameAccess->hasElements(); | |||
1376 | } | |||
1377 | ||||
1378 | Reference< XDatabaseMetaData> xMetaData = getMetaData( ); | |||
1379 | bDropAllowed = bDropAllowed || ( xMetaData.is() && xMetaData->supportsAlterTableWithDropColumn()); | |||
1380 | ||||
1381 | return bDropAllowed; | |||
1382 | } | |||
1383 | ||||
1384 | bool OTableController::isAlterAllowed() const | |||
1385 | { | |||
1386 | bool bAllowed(!m_xTable.is() || Reference<XAlterTable>(m_xTable,UNO_QUERY).is()); | |||
1387 | return bAllowed; | |||
1388 | } | |||
1389 | ||||
1390 | void OTableController::reSyncRows() | |||
1391 | { | |||
1392 | bool bAlterAllowed = isAlterAllowed(); | |||
1393 | bool bAddAllowed = isAddAllowed(); | |||
1394 | for (auto const& row : m_vRowList) | |||
1395 | { | |||
1396 | OSL_ENSURE(row,"OTableRow is null!")do { if (true && (!(row))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1396" ": "), "%s", "OTableRow is null!"); } } while (false ); | |||
1397 | OFieldDescription* pField = row->GetActFieldDescr(); | |||
1398 | if ( pField ) | |||
1399 | row->SetReadOnly(!bAlterAllowed); | |||
1400 | else | |||
1401 | row->SetReadOnly(!bAddAllowed); | |||
1402 | ||||
1403 | } | |||
1404 | static_cast<OTableDesignView*>(getView())->reSync(); // show the windows and fill with our information | |||
1405 | ||||
1406 | ClearUndoManager(); | |||
1407 | setModified(false); // and we are not modified yet | |||
1408 | } | |||
1409 | ||||
1410 | OUString OTableController::createUniqueName(const OUString& _rName) | |||
1411 | { | |||
1412 | OUString sName = _rName; | |||
1413 | Reference< XDatabaseMetaData> xMetaData = getMetaData( ); | |||
1414 | ||||
1415 | ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers()); | |||
1416 | ||||
1417 | auto lHasName = [&bCase, &sName](const std::shared_ptr<OTableRow>& rxRow) { | |||
1418 | OFieldDescription* pFieldDesc = rxRow->GetActFieldDescr(); | |||
1419 | return pFieldDesc && !pFieldDesc->GetName().isEmpty() && bCase(sName, pFieldDesc->GetName()); | |||
1420 | }; | |||
1421 | ||||
1422 | sal_Int32 i = 0; | |||
1423 | while(std::any_of(m_vRowList.begin(), m_vRowList.end(), lHasName)) | |||
1424 | { | |||
1425 | // found a second name of _rName so we need another | |||
1426 | sName = _rName + OUString::number(++i); | |||
1427 | } | |||
1428 | return sName; | |||
1429 | } | |||
1430 | ||||
1431 | OUString OTableController::getPrivateTitle() const | |||
1432 | { | |||
1433 | OUString sTitle; | |||
1434 | try | |||
1435 | { | |||
1436 | // get the table | |||
1437 | if ( !m_sName.isEmpty() && getConnection().is() ) | |||
1438 | { | |||
1439 | if ( m_xTable.is() ) | |||
1440 | sTitle = ::dbtools::composeTableName( getConnection()->getMetaData(), m_xTable, ::dbtools::EComposeRule::InDataManipulation, false ); | |||
1441 | else | |||
1442 | sTitle = m_sName; | |||
1443 | } | |||
1444 | if ( sTitle.isEmpty() ) | |||
1445 | { | |||
1446 | OUString aName = DBA_RES(STR_TBL_TITLE)::dbaccess::ResourceManager::loadString( reinterpret_cast< char const *>("STR_TBL_TITLE" "\004" u8"Table #") ); | |||
1447 | sTitle = aName.getToken(0,' ') + OUString::number(getCurrentStartNumber()); | |||
1448 | } | |||
1449 | } | |||
1450 | catch( const Exception& ) | |||
1451 | { | |||
1452 | DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx" ":" "1452" ": ", "dbaccess" );; | |||
1453 | } | |||
1454 | return sTitle; | |||
1455 | } | |||
1456 | ||||
1457 | void OTableController::reload() | |||
1458 | { | |||
1459 | loadData(); // fill the column information from the table | |||
1460 | static_cast<OTableDesignView*>(getView())->reSync(); // show the windows and fill with our information | |||
1461 | ClearUndoManager(); | |||
1462 | setModified(false); // and we are not modified yet | |||
1463 | static_cast<OTableDesignView*>(getView())->Invalidate(); | |||
1464 | } | |||
1465 | ||||
1466 | sal_Int32 OTableController::getFirstEmptyRowPosition() | |||
1467 | { | |||
1468 | sal_Int32 nRet = 0; | |||
1469 | bool bFoundElem = false; | |||
1470 | for (auto const& row : m_vRowList) | |||
1471 | { | |||
1472 | if ( !row || !row->GetActFieldDescr() || row->GetActFieldDescr()->GetName().isEmpty() ) | |||
1473 | { | |||
1474 | bFoundElem = true; | |||
1475 | break; | |||
1476 | } | |||
1477 | ++nRet; | |||
1478 | } | |||
1479 | if (!bFoundElem) | |||
1480 | { | |||
1481 | bool bReadRow = !isAddAllowed(); | |||
1482 | auto pTabEdRow = std::make_shared<OTableRow>(); | |||
1483 | pTabEdRow->SetReadOnly(bReadRow); | |||
1484 | nRet = m_vRowList.size(); | |||
1485 | m_vRowList.push_back( pTabEdRow); | |||
1486 | } | |||
1487 | return nRet; | |||
1488 | } | |||
1489 | ||||
1490 | bool OTableController::isAutoIncrementPrimaryKey() const | |||
1491 | { | |||
1492 | return getSdbMetaData().isAutoIncrementPrimaryKey(); | |||
1493 | } | |||
1494 | ||||
1495 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_VCL_PTR_HXX |
21 | #define INCLUDED_VCL_PTR_HXX |
22 | |
23 | #include <sal/config.h> |
24 | |
25 | #include <rtl/ref.hxx> |
26 | |
27 | #include <utility> |
28 | #include <type_traits> |
29 | |
30 | #ifdef DBG_UTIL |
31 | #ifndef _WIN32 |
32 | #include <vcl/vclmain.hxx> |
33 | #endif |
34 | #endif |
35 | |
36 | class VclReferenceBase; |
37 | |
38 | namespace vcl::detail { |
39 | |
40 | template<typename> |
41 | constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; } |
42 | |
43 | template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase( |
44 | int (*)[sizeof(T)]) |
45 | { return std::is_base_of<VclReferenceBase, T>::value; } |
46 | |
47 | } // namespace vcl::detail |
48 | |
49 | /** |
50 | * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses. |
51 | * |
52 | * For more details on the design please see vcl/README.lifecycle |
53 | * |
54 | * @param reference_type must be a subclass of vcl::Window |
55 | */ |
56 | template <class reference_type> |
57 | class VclPtr |
58 | { |
59 | static_assert( |
60 | vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>( |
61 | nullptr), |
62 | "template argument type must be derived from VclReferenceBase"); |
63 | |
64 | ::rtl::Reference<reference_type> m_rInnerRef; |
65 | |
66 | public: |
67 | /** Constructor... |
68 | */ |
69 | VclPtr() |
70 | : m_rInnerRef() |
71 | {} |
72 | |
73 | /** Constructor... |
74 | */ |
75 | VclPtr (reference_type * pBody) |
76 | : m_rInnerRef(pBody) |
77 | {} |
78 | |
79 | /** Constructor... that doesn't take a ref. |
80 | */ |
81 | VclPtr (reference_type * pBody, __sal_NoAcquire) |
82 | : m_rInnerRef(pBody, SAL_NO_ACQUIRE) |
83 | {} |
84 | |
85 | /** Up-casting conversion constructor: Copies interface reference. |
86 | |
87 | Does not work for up-casts to ambiguous bases. For the special case of |
88 | up-casting to Reference< XInterface >, see the corresponding conversion |
89 | operator. |
90 | |
91 | @param rRef another reference |
92 | */ |
93 | template< class derived_type > |
94 | VclPtr( |
95 | const VclPtr< derived_type > & rRef, |
96 | typename std::enable_if< |
97 | std::is_base_of<reference_type, derived_type>::value, int>::type |
98 | = 0 ) |
99 | : m_rInnerRef( static_cast<reference_type*>(rRef) ) |
100 | { |
101 | } |
102 | |
103 | #if defined(DBG_UTIL) && !defined(_WIN32) |
104 | virtual ~VclPtr() |
105 | { |
106 | assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain ::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 106, __extension__ __PRETTY_FUNCTION__)); |
107 | // We can be one of the intermediate counts, but if we are the last |
108 | // VclPtr keeping this object alive, then something forgot to call dispose(). |
109 | assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef ->isDisposed() || m_rInnerRef->getRefCount() > 1) && "someone forgot to call dispose()") ? void (0) : __assert_fail ("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\"" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 110, __extension__ __PRETTY_FUNCTION__)) |
110 | && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef ->isDisposed() || m_rInnerRef->getRefCount() > 1) && "someone forgot to call dispose()") ? void (0) : __assert_fail ("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\"" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 110, __extension__ __PRETTY_FUNCTION__)); |
111 | } |
112 | VclPtr(VclPtr const &) = default; |
113 | VclPtr(VclPtr &&) = default; |
114 | VclPtr & operator =(VclPtr const &) = default; |
115 | VclPtr & operator =(VclPtr &&) = default; |
116 | #endif |
117 | |
118 | /** |
119 | * A construction helper for VclPtr. Since VclPtr types are created |
120 | * with a reference-count of one - to help fit into the existing |
121 | * code-flow; this helps us to construct them easily. |
122 | * |
123 | * For more details on the design please see vcl/README.lifecycle |
124 | * |
125 | * @tparam reference_type must be a subclass of vcl::Window |
126 | */ |
127 | template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg) |
128 | { |
129 | return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ); |
130 | } |
131 | |
132 | /** Probably most common used: handle->someBodyOp(). |
133 | */ |
134 | reference_type * operator->() const |
135 | { |
136 | return m_rInnerRef.get(); |
137 | } |
138 | |
139 | /** Get the body. Can be used instead of operator->(). |
140 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() |
141 | are the same. |
142 | */ |
143 | reference_type * get() const |
144 | { |
145 | return m_rInnerRef.get(); |
146 | } |
147 | |
148 | void set(reference_type *pBody) |
149 | { |
150 | m_rInnerRef.set(pBody); |
151 | } |
152 | |
153 | void reset(reference_type *pBody) |
154 | { |
155 | m_rInnerRef.set(pBody); |
156 | } |
157 | |
158 | /** Up-casting copy assignment operator. |
159 | |
160 | Does not work for up-casts to ambiguous bases. |
161 | |
162 | @param rRef another reference |
163 | */ |
164 | template<typename derived_type> |
165 | typename std::enable_if< |
166 | std::is_base_of<reference_type, derived_type>::value, |
167 | VclPtr &>::type |
168 | operator =(VclPtr<derived_type> const & rRef) |
169 | { |
170 | m_rInnerRef.set(rRef.get()); |
171 | return *this; |
172 | } |
173 | |
174 | VclPtr & operator =(reference_type * pBody) |
175 | { |
176 | m_rInnerRef.set(pBody); |
177 | return *this; |
178 | } |
179 | |
180 | operator reference_type * () const |
181 | { |
182 | return m_rInnerRef.get(); |
183 | } |
184 | |
185 | explicit operator bool () const |
186 | { |
187 | return m_rInnerRef.get() != nullptr; |
188 | } |
189 | |
190 | void clear() |
191 | { |
192 | m_rInnerRef.clear(); |
193 | } |
194 | |
195 | void reset() |
196 | { |
197 | m_rInnerRef.clear(); |
198 | } |
199 | |
200 | void disposeAndClear() |
201 | { |
202 | // hold it alive for the lifetime of this method |
203 | ::rtl::Reference<reference_type> aTmp(m_rInnerRef); |
204 | m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-) |
205 | if (aTmp.get()) { |
206 | aTmp->disposeOnce(); |
207 | } |
208 | } |
209 | |
210 | /** Needed to place VclPtr's into STL collection. |
211 | */ |
212 | bool operator< (const VclPtr<reference_type> & handle) const |
213 | { |
214 | return (m_rInnerRef < handle.m_rInnerRef); |
215 | } |
216 | }; // class VclPtr |
217 | |
218 | template<typename T1, typename T2> |
219 | inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
220 | return p1.get() == p2.get(); |
221 | } |
222 | |
223 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2) |
224 | { |
225 | return p1.get() == p2; |
226 | } |
227 | |
228 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) { |
229 | return p1.get() == p2; |
230 | } |
231 | |
232 | template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2) |
233 | { |
234 | return p1 == p2.get(); |
235 | } |
236 | |
237 | template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) { |
238 | return p1 == p2.get(); |
239 | } |
240 | |
241 | template<typename T1, typename T2> |
242 | inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
243 | return !(p1 == p2); |
244 | } |
245 | |
246 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2) |
247 | { |
248 | return !(p1 == p2); |
249 | } |
250 | |
251 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) { |
252 | return !(p1 == p2); |
253 | } |
254 | |
255 | template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2) |
256 | { |
257 | return !(p1 == p2); |
258 | } |
259 | |
260 | template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) { |
261 | return !(p1 == p2); |
262 | } |
263 | |
264 | /** |
265 | * A construction helper for a temporary VclPtr. Since VclPtr types |
266 | * are created with a reference-count of one - to help fit into |
267 | * the existing code-flow; this helps us to construct them easily. |
268 | * see also VclPtr::Create and ScopedVclPtr |
269 | * |
270 | * For more details on the design please see vcl/README.lifecycle |
271 | * |
272 | * @param reference_type must be a subclass of vcl::Window |
273 | */ |
274 | template <class reference_type> |
275 | class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type> |
276 | { |
277 | public: |
278 | template<typename... Arg> VclPtrInstance(Arg &&... arg) |
279 | : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ) |
280 | { |
281 | } |
282 | |
283 | /** |
284 | * Override and disallow this, to prevent people accidentally calling it and actually |
285 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
286 | */ |
287 | template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete; |
288 | }; |
289 | |
290 | template <class reference_type> |
291 | class ScopedVclPtr : public VclPtr<reference_type> |
292 | { |
293 | public: |
294 | /** Constructor... |
295 | */ |
296 | ScopedVclPtr() |
297 | : VclPtr<reference_type>() |
298 | {} |
299 | |
300 | /** Constructor |
301 | */ |
302 | ScopedVclPtr (reference_type * pBody) |
303 | : VclPtr<reference_type>(pBody) |
304 | {} |
305 | |
306 | /** Copy constructor... |
307 | */ |
308 | ScopedVclPtr (const VclPtr<reference_type> & handle) |
309 | : VclPtr<reference_type>(handle) |
310 | {} |
311 | |
312 | /** |
313 | Assignment that releases the last reference. |
314 | */ |
315 | void disposeAndReset(reference_type *pBody) |
316 | { |
317 | if (pBody != this->get()) { |
318 | VclPtr<reference_type>::disposeAndClear(); |
319 | VclPtr<reference_type>::set(pBody); |
320 | } |
321 | } |
322 | |
323 | /** |
324 | Assignment that releases the last reference. |
325 | */ |
326 | ScopedVclPtr<reference_type>& operator = (reference_type * pBody) |
327 | { |
328 | disposeAndReset(pBody); |
329 | return *this; |
330 | } |
331 | |
332 | /** Up-casting conversion constructor: Copies interface reference. |
333 | |
334 | Does not work for up-casts to ambiguous bases. For the special case of |
335 | up-casting to Reference< XInterface >, see the corresponding conversion |
336 | operator. |
337 | |
338 | @param rRef another reference |
339 | */ |
340 | template< class derived_type > |
341 | ScopedVclPtr( |
342 | const VclPtr< derived_type > & rRef, |
343 | typename std::enable_if< |
344 | std::is_base_of<reference_type, derived_type>::value, int>::type |
345 | = 0 ) |
346 | : VclPtr<reference_type>( rRef ) |
347 | { |
348 | } |
349 | |
350 | /** Up-casting assignment operator. |
351 | |
352 | Does not work for up-casts to ambiguous bases. |
353 | |
354 | @param rRef another VclPtr |
355 | */ |
356 | template<typename derived_type> |
357 | typename std::enable_if< |
358 | std::is_base_of<reference_type, derived_type>::value, |
359 | ScopedVclPtr &>::type |
360 | operator =(VclPtr<derived_type> const & rRef) |
361 | { |
362 | disposeAndReset(rRef.get()); |
363 | return *this; |
364 | } |
365 | |
366 | /** |
367 | * Override and disallow this, to prevent people accidentally calling it and actually |
368 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
369 | */ |
370 | template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete; |
371 | |
372 | ~ScopedVclPtr() |
373 | { |
374 | VclPtr<reference_type>::disposeAndClear(); |
375 | assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get( ) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 375, __extension__ __PRETTY_FUNCTION__)); // make sure there are no lingering references |
376 | } |
377 | |
378 | private: |
379 | // Most likely we don't want this default copy-constructor. |
380 | ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete; |
381 | // And certainly we don't want a default assignment operator. |
382 | ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete; |
383 | // And disallow reset as that doesn't call disposeAndClear on the original reference |
384 | void reset() = delete; |
385 | void reset(reference_type *pBody) = delete; |
386 | |
387 | protected: |
388 | ScopedVclPtr (reference_type * pBody, __sal_NoAcquire) |
389 | : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE) |
390 | {} |
391 | }; |
392 | |
393 | /** |
394 | * A construction helper for ScopedVclPtr. Since VclPtr types are created |
395 | * with a reference-count of one - to help fit into the existing |
396 | * code-flow; this helps us to construct them easily. |
397 | * |
398 | * For more details on the design please see vcl/README.lifecycle |
399 | * |
400 | * @param reference_type must be a subclass of vcl::Window |
401 | */ |
402 | #if defined _MSC_VER |
403 | #pragma warning(push) |
404 | #pragma warning(disable: 4521) // " multiple copy constructors specified" |
405 | #endif |
406 | template <class reference_type> |
407 | class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type> |
408 | { |
409 | public: |
410 | template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg) |
411 | : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ) |
412 | { |
413 | } |
414 | |
415 | /** |
416 | * Override and disallow this, to prevent people accidentally calling it and actually |
417 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
418 | */ |
419 | template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete; |
420 | |
421 | private: |
422 | // Prevent the above perfect forwarding ctor from hijacking (accidental) |
423 | // attempts at ScopedVclPtrInstance copy construction (where the hijacking |
424 | // would typically lead to somewhat obscure error messages); both non-const |
425 | // and const variants are needed here, as the ScopedVclPtr base class has a |
426 | // const--variant copy ctor, so the implicitly declared copy ctor for |
427 | // ScopedVclPtrInstance would also be the const variant, so non-const copy |
428 | // construction attempts would be hijacked by the perfect forwarding ctor; |
429 | // but if we only declared a non-const variant here, the const variant would |
430 | // no longer be implicitly declared (as there would already be an explicitly |
431 | // declared copy ctor), so const copy construction attempts would then be |
432 | // hijacked by the perfect forwarding ctor: |
433 | ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete; |
434 | ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete; |
435 | }; |
436 | #if defined _MSC_VER |
437 | #pragma warning(pop) |
438 | #endif |
439 | |
440 | #endif // INCLUDED_VCL_PTR_HXX |
441 | |
442 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_RTL_REF_HXX | ||||||||||||||||
21 | #define INCLUDED_RTL_REF_HXX | ||||||||||||||||
22 | |||||||||||||||||
23 | #include "sal/config.h" | ||||||||||||||||
24 | |||||||||||||||||
25 | #include <cassert> | ||||||||||||||||
26 | #include <cstddef> | ||||||||||||||||
27 | #include <functional> | ||||||||||||||||
28 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||||||||
29 | #include <type_traits> | ||||||||||||||||
30 | #endif | ||||||||||||||||
31 | |||||||||||||||||
32 | #include "sal/types.h" | ||||||||||||||||
33 | |||||||||||||||||
34 | namespace rtl | ||||||||||||||||
35 | { | ||||||||||||||||
36 | |||||||||||||||||
37 | /** Template reference class for reference type. | ||||||||||||||||
38 | */ | ||||||||||||||||
39 | template <class reference_type> | ||||||||||||||||
40 | class Reference | ||||||||||||||||
41 | { | ||||||||||||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||||||||||||
43 | */ | ||||||||||||||||
44 | reference_type * m_pBody; | ||||||||||||||||
45 | |||||||||||||||||
46 | |||||||||||||||||
47 | public: | ||||||||||||||||
48 | /** Constructor... | ||||||||||||||||
49 | */ | ||||||||||||||||
50 | Reference() | ||||||||||||||||
51 | : m_pBody (NULL__null) | ||||||||||||||||
52 | {} | ||||||||||||||||
53 | |||||||||||||||||
54 | |||||||||||||||||
55 | /** Constructor... | ||||||||||||||||
56 | */ | ||||||||||||||||
57 | Reference (reference_type * pBody, __sal_NoAcquire) | ||||||||||||||||
58 | : m_pBody (pBody) | ||||||||||||||||
59 | { | ||||||||||||||||
60 | } | ||||||||||||||||
61 | |||||||||||||||||
62 | /** Constructor... | ||||||||||||||||
63 | */ | ||||||||||||||||
64 | Reference (reference_type * pBody) | ||||||||||||||||
65 | : m_pBody (pBody) | ||||||||||||||||
66 | { | ||||||||||||||||
67 | if (m_pBody) | ||||||||||||||||
68 | m_pBody->acquire(); | ||||||||||||||||
69 | } | ||||||||||||||||
70 | |||||||||||||||||
71 | /** Copy constructor... | ||||||||||||||||
72 | */ | ||||||||||||||||
73 | Reference (const Reference<reference_type> & handle) | ||||||||||||||||
74 | : m_pBody (handle.m_pBody) | ||||||||||||||||
75 | { | ||||||||||||||||
76 | if (m_pBody) | ||||||||||||||||
77 | m_pBody->acquire(); | ||||||||||||||||
78 | } | ||||||||||||||||
79 | |||||||||||||||||
80 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||||||||
81 | /** Move constructor... | ||||||||||||||||
82 | */ | ||||||||||||||||
83 | Reference (Reference<reference_type> && handle) noexcept | ||||||||||||||||
84 | : m_pBody (handle.m_pBody) | ||||||||||||||||
85 | { | ||||||||||||||||
86 | handle.m_pBody = nullptr; | ||||||||||||||||
87 | } | ||||||||||||||||
88 | #endif | ||||||||||||||||
89 | |||||||||||||||||
90 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||||||||
91 | /** Up-casting conversion constructor: Copies interface reference. | ||||||||||||||||
92 | |||||||||||||||||
93 | Does not work for up-casts to ambiguous bases. | ||||||||||||||||
94 | |||||||||||||||||
95 | @param rRef another reference | ||||||||||||||||
96 | */ | ||||||||||||||||
97 | template< class derived_type > | ||||||||||||||||
98 | inline Reference( | ||||||||||||||||
99 | const Reference< derived_type > & rRef, | ||||||||||||||||
100 | std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 ) | ||||||||||||||||
101 | : m_pBody (rRef.get()) | ||||||||||||||||
102 | { | ||||||||||||||||
103 | if (m_pBody) | ||||||||||||||||
104 | m_pBody->acquire(); | ||||||||||||||||
105 | } | ||||||||||||||||
106 | #endif | ||||||||||||||||
107 | |||||||||||||||||
108 | /** Destructor... | ||||||||||||||||
109 | */ | ||||||||||||||||
110 | ~Reference() COVERITY_NOEXCEPT_FALSE | ||||||||||||||||
111 | { | ||||||||||||||||
112 | if (m_pBody
| ||||||||||||||||
113 | m_pBody->release(); | ||||||||||||||||
| |||||||||||||||||
114 | } | ||||||||||||||||
115 | |||||||||||||||||
116 | /** Set... | ||||||||||||||||
117 | Similar to assignment. | ||||||||||||||||
118 | */ | ||||||||||||||||
119 | Reference<reference_type> & | ||||||||||||||||
120 | SAL_CALL set (reference_type * pBody) | ||||||||||||||||
121 | { | ||||||||||||||||
122 | if (pBody) | ||||||||||||||||
123 | pBody->acquire(); | ||||||||||||||||
124 | reference_type * const pOld = m_pBody; | ||||||||||||||||
125 | m_pBody = pBody; | ||||||||||||||||
126 | if (pOld) | ||||||||||||||||
127 | pOld->release(); | ||||||||||||||||
128 | return *this; | ||||||||||||||||
129 | } | ||||||||||||||||
130 | |||||||||||||||||
131 | /** Assignment. | ||||||||||||||||
132 | Unbinds this instance from its body (if bound) and | ||||||||||||||||
133 | bind it to the body represented by the handle. | ||||||||||||||||
134 | */ | ||||||||||||||||
135 | Reference<reference_type> & | ||||||||||||||||
136 | SAL_CALL operator= (const Reference<reference_type> & handle) | ||||||||||||||||
137 | { | ||||||||||||||||
138 | return set( handle.m_pBody ); | ||||||||||||||||
139 | } | ||||||||||||||||
140 | |||||||||||||||||
141 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||||||||
142 | /** Assignment. | ||||||||||||||||
143 | * Unbinds this instance from its body (if bound), | ||||||||||||||||
144 | * bind it to the body represented by the handle, and | ||||||||||||||||
145 | * set the body represented by the handle to nullptr. | ||||||||||||||||
146 | */ | ||||||||||||||||
147 | Reference<reference_type> & | ||||||||||||||||
148 | operator= (Reference<reference_type> && handle) | ||||||||||||||||
149 | { | ||||||||||||||||
150 | // self-movement guts ourself | ||||||||||||||||
151 | if (m_pBody) | ||||||||||||||||
152 | m_pBody->release(); | ||||||||||||||||
153 | m_pBody = handle.m_pBody; | ||||||||||||||||
154 | handle.m_pBody = nullptr; | ||||||||||||||||
155 | return *this; | ||||||||||||||||
156 | } | ||||||||||||||||
157 | #endif | ||||||||||||||||
158 | |||||||||||||||||
159 | /** Assignment... | ||||||||||||||||
160 | */ | ||||||||||||||||
161 | Reference<reference_type> & | ||||||||||||||||
162 | SAL_CALL operator= (reference_type * pBody) | ||||||||||||||||
163 | { | ||||||||||||||||
164 | return set( pBody ); | ||||||||||||||||
165 | } | ||||||||||||||||
166 | |||||||||||||||||
167 | /** Unbind the body from this handle. | ||||||||||||||||
168 | Note that for a handle representing a large body, | ||||||||||||||||
169 | "handle.clear().set(new body());" _might_ | ||||||||||||||||
170 | perform a little bit better than "handle.set(new body());", | ||||||||||||||||
171 | since in the second case two large objects exist in memory | ||||||||||||||||
172 | (the old body and the new body). | ||||||||||||||||
173 | */ | ||||||||||||||||
174 | Reference<reference_type> & SAL_CALL clear() | ||||||||||||||||
175 | { | ||||||||||||||||
176 | if (m_pBody) | ||||||||||||||||
177 | { | ||||||||||||||||
178 | reference_type * const pOld = m_pBody; | ||||||||||||||||
179 | m_pBody = NULL__null; | ||||||||||||||||
180 | pOld->release(); | ||||||||||||||||
181 | } | ||||||||||||||||
182 | return *this; | ||||||||||||||||
183 | } | ||||||||||||||||
184 | |||||||||||||||||
185 | |||||||||||||||||
186 | /** Get the body. Can be used instead of operator->(). | ||||||||||||||||
187 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() | ||||||||||||||||
188 | are the same. | ||||||||||||||||
189 | */ | ||||||||||||||||
190 | reference_type * SAL_CALL get() const | ||||||||||||||||
191 | { | ||||||||||||||||
192 | return m_pBody; | ||||||||||||||||
193 | } | ||||||||||||||||
194 | |||||||||||||||||
195 | |||||||||||||||||
196 | /** Probably most common used: handle->someBodyOp(). | ||||||||||||||||
197 | */ | ||||||||||||||||
198 | reference_type * SAL_CALL operator->() const | ||||||||||||||||
199 | { | ||||||||||||||||
200 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 200, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||||||
201 | return m_pBody; | ||||||||||||||||
202 | } | ||||||||||||||||
203 | |||||||||||||||||
204 | |||||||||||||||||
205 | /** Allows (*handle).someBodyOp(). | ||||||||||||||||
206 | */ | ||||||||||||||||
207 | reference_type & SAL_CALL operator*() const | ||||||||||||||||
208 | { | ||||||||||||||||
209 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 209, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||||||
210 | return *m_pBody; | ||||||||||||||||
211 | } | ||||||||||||||||
212 | |||||||||||||||||
213 | |||||||||||||||||
214 | /** Returns True if the handle does point to a valid body. | ||||||||||||||||
215 | */ | ||||||||||||||||
216 | bool SAL_CALL is() const | ||||||||||||||||
217 | { | ||||||||||||||||
218 | return (m_pBody != NULL__null); | ||||||||||||||||
219 | } | ||||||||||||||||
220 | |||||||||||||||||
221 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||||||||
222 | /** Returns True if the handle does point to a valid body. | ||||||||||||||||
223 | */ | ||||||||||||||||
224 | explicit operator bool() const | ||||||||||||||||
225 | { | ||||||||||||||||
226 | return is(); | ||||||||||||||||
227 | } | ||||||||||||||||
228 | #endif | ||||||||||||||||
229 | |||||||||||||||||
230 | /** Returns True if this points to pBody. | ||||||||||||||||
231 | */ | ||||||||||||||||
232 | bool SAL_CALL operator== (const reference_type * pBody) const | ||||||||||||||||
233 | { | ||||||||||||||||
234 | return (m_pBody == pBody); | ||||||||||||||||
235 | } | ||||||||||||||||
236 | |||||||||||||||||
237 | |||||||||||||||||
238 | /** Returns True if handle points to the same body. | ||||||||||||||||
239 | */ | ||||||||||||||||
240 | bool | ||||||||||||||||
241 | SAL_CALL operator== (const Reference<reference_type> & handle) const | ||||||||||||||||
242 | { | ||||||||||||||||
243 | return (m_pBody == handle.m_pBody); | ||||||||||||||||
244 | } | ||||||||||||||||
245 | |||||||||||||||||
246 | |||||||||||||||||
247 | /** Needed to place References into STL collection. | ||||||||||||||||
248 | */ | ||||||||||||||||
249 | bool | ||||||||||||||||
250 | SAL_CALL operator!= (const Reference<reference_type> & handle) const | ||||||||||||||||
251 | { | ||||||||||||||||
252 | return (m_pBody != handle.m_pBody); | ||||||||||||||||
253 | } | ||||||||||||||||
254 | |||||||||||||||||
255 | |||||||||||||||||
256 | /** Needed to place References into STL collection. | ||||||||||||||||
257 | */ | ||||||||||||||||
258 | bool | ||||||||||||||||
259 | SAL_CALL operator< (const Reference<reference_type> & handle) const | ||||||||||||||||
260 | { | ||||||||||||||||
261 | return (m_pBody < handle.m_pBody); | ||||||||||||||||
262 | } | ||||||||||||||||
263 | |||||||||||||||||
264 | |||||||||||||||||
265 | /** Needed to place References into STL collection. | ||||||||||||||||
266 | */ | ||||||||||||||||
267 | bool | ||||||||||||||||
268 | SAL_CALL operator> (const Reference<reference_type> & handle) const | ||||||||||||||||
269 | { | ||||||||||||||||
270 | return (m_pBody > handle.m_pBody); | ||||||||||||||||
271 | } | ||||||||||||||||
272 | }; | ||||||||||||||||
273 | |||||||||||||||||
274 | } // namespace rtl | ||||||||||||||||
275 | |||||||||||||||||
276 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||||||||
277 | namespace std | ||||||||||||||||
278 | { | ||||||||||||||||
279 | |||||||||||||||||
280 | /// @cond INTERNAL | ||||||||||||||||
281 | /** | ||||||||||||||||
282 | Make rtl::Reference hashable by default for use in STL containers. | ||||||||||||||||
283 | |||||||||||||||||
284 | @since LibreOffice 6.3 | ||||||||||||||||
285 | */ | ||||||||||||||||
286 | template<typename T> | ||||||||||||||||
287 | struct hash<::rtl::Reference<T>> | ||||||||||||||||
288 | { | ||||||||||||||||
289 | std::size_t operator()(::rtl::Reference<T> const & s) const | ||||||||||||||||
290 | { return std::size_t(s.get()); } | ||||||||||||||||
291 | }; | ||||||||||||||||
292 | /// @endcond | ||||||||||||||||
293 | |||||||||||||||||
294 | } | ||||||||||||||||
295 | |||||||||||||||||
296 | #endif | ||||||||||||||||
297 | |||||||||||||||||
298 | #endif /* ! INCLUDED_RTL_REF_HXX */ | ||||||||||||||||
299 | |||||||||||||||||
300 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_VCL_Reference_HXX |
20 | #define INCLUDED_VCL_Reference_HXX |
21 | |
22 | #include <vcl/dllapi.h> |
23 | #include <osl/interlck.h> |
24 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
32 | void acquire() const |
33 | { |
34 | osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1); |
35 | } |
36 | |
37 | void release() const |
38 | { |
39 | if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |